Logo Search packages:      
Sourcecode: xconq version File versions  Download package

maccmd.c

/* Commands for the Mac interface to Xconq.
   Copyright (C) 1992-2000 Stanley T. Shebs.

Xconq is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.  See the file COPYING.  */

#include "conq.h"
#include "print.h"
#include "macconq.h"

/* Define to enable (but not activate) profiling. */
#undef PROFILING

/* Define PROFILING if CodeWarrior profiling is on. 
Also include Profiler.h if not already included. */
#if __profile__
#include <Profiler.h>
#define PROFILING
#endif

#ifdef PROFILING
#ifdef THINK_C                
extern int _trace;      /* Not used by CodeWarrior. */
#include <profile.h>
#endif
#endif

extern WindowPtr playersetupwin;

extern int forcedtoresign;

int position_set_modally;

Point modal_point;

Map *modal_map;

#ifdef DESIGNERS
#define side_may_select(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
#define valid_selection(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
#else
#define side_may_select(unit) (in_play(unit) && ((unit)->side == dside))
#define valid_selection(unit) (in_play(unit) && ((unit)->side == dside))
#endif

extern char *cursavename;

int givetakeprefixarg;

extern Side *tmpcmdside;

/* Local function declarations. */

static int get_a_position(Map **map, int *xp, int *yp, int *dirp);
static int get_a_unit(Map **mapp, Unit **unitp);
static int get_a_visible_unit(Map **mapp, Unit **unitp);
static int add_unit_position(Unit *unit);
static void message_dialog(int sidenum);
static int do_one_add_terrain(Unit *unit);
static int do_one_attack(Unit *unit);
static void unit_do_build_2(Unit *unit);
static int do_one_collect(Unit *unit);
static int do_one_fire(Unit *unit);
static int do_one_fire_into(Unit *unit);
static int do_one_move_to(Unit *unit);
static int do_one_occupant(Unit *unit);
static int do_one_remove_terrain(Unit *unit);
static int do_one_repair(Unit *unit);
static int do_one_set_name(Unit *unit);
static int do_one_dir_move(Unit *unit);
static int do_one_dir_multiple_move(Unit *unit);
static void create_command_window(void);
static void get_command_and_do(void);
static int unit_rename_dialog(Unit *unit);

void cmd_error(Side *side, char *fmt, ...);

/* Static (local) variables. */

static int tmpcmdarg;
static int tmprecurse;

static int tmpcmdx, tmpcmdy, tmpcmddir;

static Unit *tmpcmdunit;

/* Prefixed numeric argument to commands. */

static int tmpdir;

/* This flag is set to prevent running an "other" command when already
   executing an "other" command. */

static int doingother = FALSE;

/* Given a character, find a command for it and execute. */

void
do_keyboard_command(int key)
{
    void (*fn)(void);

      DGprintf("Typed '%c' (0x%x)\n", key, key);
      if (between('0', key, '9')) {
            /* Add a decimal digit to the prefix argument. */
            if (dside->prefixarg < 0)
              dside->prefixarg = 0;
            dside->prefixarg += dside->prefixarg * 10 + (key - '0');
            /* (should add some sort of feedback) */
      } else {
            execute_command(dside, key);
      }
}

int
get_a_position(Map **mapp, int *xp, int *yp, int *dirp)
{
      Point at;

      if (position_set_modally) {
            position_set_modally = FALSE;
            *mapp = modal_map;
            return m_nearest_boundary(*mapp, modal_point.h, modal_point.v, xp, yp, dirp);
      } else if ((*mapp = frontmap) != NULL) {

            GetMouse(&at);
            return m_nearest_boundary(*mapp, at.h, at.v, xp, yp, dirp);
      }
      return FALSE;
}

int
get_a_unit(Map **mapp, Unit **unitp)
{
      Point at;

      if (position_set_modally) {
            position_set_modally = FALSE;
            *mapp = modal_map;
            return m_nearest_unit(*mapp, modal_point.h, modal_point.v, unitp);
      } else if ((*mapp = frontmap) != NULL) {

            GetMouse(&at);
            return m_nearest_unit(*mapp, at.h, at.v, unitp);
      }
      return FALSE;
}

int
get_a_visible_unit(Map **mapp, Unit **unitp)
{
      int rslt = FALSE;
      Point at;

      if (position_set_modally) {
            position_set_modally = FALSE;
            *mapp = modal_map;
            rslt = m_nearest_unit(*mapp, modal_point.h, modal_point.v, unitp);
      } else if ((*mapp = frontmap) != NULL) {

            GetMouse(&at);
            rslt = m_nearest_unit(*mapp, at.h, at.v, unitp);
      }
      if (rslt
            && !(*mapp)->see_all
            && !units_visible(dside, (*unitp)->x, (*unitp)->y)
            )
        rslt = FALSE;
      return rslt;
}

static UnitVector *selvec;

UnitVector *
get_selected_units(Side *side)
{
      int i, rslt, numcould = 0, numnot = 0;
      Map *map;
      List *list;  
      UnitCloseup *closeup;
      Unit *unit;

      if (selvec == NULL)
        selvec = make_unit_vector(100);
      clear_unit_vector(selvec);

      if (frontmap) {
            for (i = 0; i < frontmap->numselections; ++i) {
                  unit = frontmap->selections[i];
                  /* Don't apply to selected units that we don't control. */
                  if (in_play(unit) && side_controls_unit(dside, unit)) {
                      selvec = add_unit_to_vector(selvec, unit, 0);
                  }
            }
      } else if ((list = list_from_window(topWindow)) != NULL) {
            if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
                selvec = add_unit_to_vector(selvec, unit, 0);
            }
      } else if ((closeup = unit_closeup_from_window(topFloat)) != NULL) {
            unit = closeup->unit;
            /* Don't apply to units that we don't control. */
            if (side_controls_unit(dside, unit)) {
                selvec = add_unit_to_vector(selvec, unit, 0);
            }
      } else if (maplist != NULL) {
            map = maplist;
            for (i = 0; i < map->numselections; ++i) {
                  unit = map->selections[i];
                  /* Don't apply to selected units that we don't control. */
                  if (in_play(unit) && side_controls_unit(dside, unit)) {
                      selvec = add_unit_to_vector(selvec, unit, 0);
                  }
            }
      }
      return selvec;
}

/* Start of alphabetized commands. */

void do_flash(Side *side) {}
void do_world_map(Side *side) {}
void do_unit_closeup(Side *side) {}
void do_side_closeup(Side *side) {}
void do_orders_popup(Side *side) {}
void do_new_map(Side *side) {}
void do_map(Side *side) {}

void
do_add_terrain(Side *side)
{
    int x, y, dir;
      Map *map;

      if (get_a_position(&map, &x, &y, &dir)) {
            tmpcmdx = x;  tmpcmdy = y;  tmpcmddir = dir;
            apply_to_all_selected(do_one_add_terrain, TRUE);
            return;
      }
      beep();
}

static int
do_one_add_terrain(Unit *unit)
{
      int u, t, t1, x, y, dir, tfirst = -1, numtypes, possibles[MAXTTYPES];

    u = unit->type;
    numtypes = 0;
      for_all_terrain_types(t) {
            if (ut_acp_to_add_terrain(u, t) > 0) {
                  possibles[numtypes++] = t;
            }
      }
      if (numtypes == 0) {
            return FALSE;
      } else if (numtypes == 1) {
            t1 = possibles[0];
      } else {
            /* should have better way to choose type */
            if (between(0, dside->prefixarg, numtypes - 1))
              t1 = possibles[dside->prefixarg];
            else {
                  notify(dside, "Prefix should be 0 to %d", numtypes - 1); 
                  return FALSE;
            }
      }
      /* (should put following in ui.c?) */
      switch (t_subtype(t1)) {
            case cellsubtype:
                  if (valid(check_alter_cell_action(unit, unit, tmpcmdx, tmpcmdy, t1))) {
                        if (net_prep_alter_cell_action(unit, unit, tmpcmdx, tmpcmdy, t1))
                          return TRUE;
                  }
                  break;
            case bordersubtype:
            case connectionsubtype:
                if (distance(tmpcmdx, tmpcmdy, unit->x, unit->y) <= ut_alter_range(u, t1)) {
                        x = tmpcmdx;  y = tmpcmdy;
                        dir = tmpcmddir;
                  } else {
                        x = unit->x;  y = unit->y;
                        dir = approx_dir(tmpcmdx - unit->x, tmpcmdy - unit->y);
                  }
                  if (valid(check_add_terrain_action(unit, unit, x, y, dir, t1))) {
                        if (net_prep_add_terrain_action(unit, unit, x, y, dir, t1))
                          return TRUE;
                  }
                  break;
            case coatingsubtype:
                  break;
      }
      return FALSE;
}

void
do_attack(Side *side)
{
      Map *map;
      
      if (get_a_visible_unit(&map, &tmpcmdunit)) {
            apply_to_all_selected(do_one_attack, TRUE);
            return;
      }
      beep();
}

static int
do_one_attack(Unit *atker)
{
      int i;
      Unit *other;

      other = tmpcmdunit;
      if (other != NULL
            && other != atker
            && other->side != atker->side) {
            if (distance(atker->x, atker->y, other->x, other->y) <= 1
                  && valid(check_attack_action(atker, atker, other, 100))) {
                  net_prep_attack_action(atker, atker, other, 100);
                  return TRUE;
            } else if (valid(check_fire_at_action(atker, atker, other, -1))) {
                  net_prep_fire_at_action(atker, atker, other, -1);
                  return TRUE;
            }
      }
      return FALSE;
}

void
do_build(Side *side)
{
      int i;
      List *list;  
      UnitCloseup *closeup;
      Unit *unit;

      list = list_from_window(topWindow);
      if (list != NULL) {
            unit = selected_unit_in_list(list);
            if (unit != NULL 
                && can_build_or_help(unit)
                && side_controls_unit(dside, unit)) {
                  show_unit_build_dialog(unit);
                  return;
            }
            return;
      }
      closeup = unit_closeup_from_window(topFloat);
      if (closeup != NULL) {
            unit = closeup->unit;
            if (unit != NULL 
                && can_build_or_help(unit)
                && side_controls_unit(dside, unit)) {
                  show_unit_build_dialog(unit);
                  return;
            }
            return;
      }
      if (frontmap) {
            for (i = 0; i < frontmap->numselections; ++i) {
                  unit = frontmap->selections[i];
                  if (unit != NULL 
                      && can_build_or_help(unit)
                      && side_controls_unit(dside, unit)) {
                        show_unit_build_dialog(unit);
                        return;
                  }
            }
            return;
      }
      /* No way to figure out the unit to be building with, so complain. */
      beep();
}

void
unit_do_build_2(Unit *unit)
{
    extern int editedrunlength;

      show_construction_window();
      if (dside->prefixarg > 0)
        set_construction_run_length(dside->prefixarg);
      if (dside->prefixarg > 0)
        editedrunlength = dside->prefixarg;
      else
        editedrunlength = -1;
      select_unit_in_construction_window(unit);
      select_type_in_construction_window(favored_type(unit));
}

int mtocollect;

void
do_collect(Side *side)
{
    char *arg, *rest;

      mtocollect = NONMTYPE;
      if (nummtypes == 0) {
            cmd_error(dside, "No materials to collect");
            return;
      }
      if (!empty_string(cmdargstr)) {
            rest = get_next_arg(cmdargstr, tmpbuf, &arg);
            mtocollect = mtype_from_name(arg);
      } else {
            cmd_error(dside, "No material name given");
            return;
      }
      if (!is_material_type(mtocollect)) {
            cmd_error(dside, "`%s' is not a recognized material name", arg);
            return;
      }
      apply_to_all_selected(do_one_collect, TRUE);    
}

int
do_one_collect(Unit *unit)
{
      if (unit->plan) {
            net_set_collect_task(unit, mtocollect, unit->x, unit->y);
            return TRUE;
      }
      return FALSE;
}

void
do_copying(Side *side)
{
      show_help_window(copying_help_node);
}

/* Command all selected mobile units to move in a given direction. */

/* The function that gets called on each selected unit. */

int
do_one_dir_move(Unit *unit)
{
    int nx, ny;

      if (mobile(unit->type)) {
            if (point_in_dir(unit->x, unit->y, tmpdir, &nx, &ny)) {
                  return advance_into_cell(dside, unit, nx, ny, unit_at(nx, ny), NULL);
            }
            return FALSE;
      }
      return FALSE;
}

/* The command function proper. */

void
do_dir(Side *side)
{
      int ndirs, dir1, dir2, modif;

      if (frontmap) {
            ndirs = char_to_dir(tmpkey, &dir1, &dir2, &modif);
            if (ndirs >= 1) {
                  tmpdir = dir1;
            } else {
                  beep();
                  return;
            }
            apply_to_all_selected(do_one_dir_move, TRUE);
            if (frontmap->moveonclick)
              frontmap->scrolltocurunit = TRUE;
      }
}

/* Command all selected mobile units to move in a given direction. */

/* The function that gets called on each selected unit. */

int
do_one_dir_multiple_move(Unit *unit)
{
      if (mobile(unit->type)) {
            net_set_move_dir_task(unit, tmpdir, (dside->prefixarg <= 0 ? 9999 : dside->prefixarg));
            return TRUE;
      }
      return FALSE;
}

/* The command function proper. */

void
do_dir_multiple(Side *side)
{
      int ndirs, dir1, dir2, modif;

      if (frontmap) {
            ndirs = char_to_dir(tmpkey, &dir1, &dir2, &modif);
            if (ndirs >= 1) {
                  tmpdir = dir1;
            } else {
                  beep();
                  return;
            }
            apply_to_all_selected(do_one_dir_multiple_move, TRUE);
            if (frontmap->moveonclick)
              frontmap->scrolltocurunit = TRUE;
      }
}

void
do_distance(Side *side)
{
    notify(dside, "Click, then drag to location to which you want the distance.");
      query_position_modally(DISTANCE_MODAL);
}

#if 0 /* (should fix this) */
void
do_end_turn(Side *side)
{
      /* <return> is also interpreted by dialogs, so special-case this, depending
         on which window was in front. */
      if (topWindow == constructionwin) {
            Point pt;
            extern ControlHandle constructbutton;
            
            pt.h = (*constructbutton)->contrlRect.left + 8;
            pt.v = (*constructbutton)->contrlRect.top + 8;
            do_mouse_down_construction(pt, 0);
      } else {
            net_finish_turn(dside);
      }
}
#endif

void
do_escape(Side *side)
{
      map_modal = NO_MODAL;
}

void
do_fire(Side *side)
{
      Map *map;
      
      if (!get_a_visible_unit(&map, &tmpcmdunit)) {
            beep();
            return;
      }
      apply_to_all_selected(do_one_fire, TRUE);
}

static int
do_one_fire(Unit *atker)
{
      Unit *other;

      other = tmpcmdunit;
      if (other != NULL
            && other != atker
            && other->side != atker->side
            && valid(check_fire_at_action(atker, atker, other, -1))) {
            net_prep_fire_at_action(atker, atker, other, -1);
            return TRUE;
      }
      return FALSE;
}

void
do_fire_into(Side *side)
{
      Map *map;
      
      if (!get_a_position(&map, &tmpcmdx, &tmpcmdy, &tmpcmddir)) {
            beep();
            return;
      }
      apply_to_all_selected(do_one_fire_into, TRUE);
}

static int
do_one_fire_into(Unit *atker)
{
      int x, y;

      x = tmpcmdx;  y = tmpcmdy;    
      if (valid(check_fire_into_action(atker, atker, x, y, 0, -1))) {
            net_prep_fire_into_action(atker, atker, x, y, 0, -1);
            return TRUE;
      }
      return FALSE;
}

void
do_follow_action(Side *side)
{
      if (frontmap) {
            frontmap->follow_action = !frontmap->follow_action;
            if (frontmap->follow_action)
              notify(dside, "Following the action on map %d", frontmap->id);
            else
              notify(dside, "No longer following action on map %d", frontmap->id);
      } else {
            beep();
      }
}

void
do_give_unit(Side *side)
{
      int sn = 0;

    if (side->prefixarg >= 0) {
            if (side->prefixarg <= numsides) {
                  sn = side->prefixarg;
            } else {
                  beep();
                  return;
            }
    }
      tmpcmdside = side_n(sn);
      apply_to_all_selected(do_one_give_unit, TRUE);
}

int
do_one_give_unit(Unit *unit)
{
      if (unit->side == tmpcmdside)
        return FALSE;
#ifdef DESIGNERS
      if (is_designer(dside)) {
            net_designer_change_side(unit, tmpcmdside);
            return TRUE;
      }
#endif /* DESIGNERS */
    if (0 /* unit is a type that cannot act */) {
            /* (should add case for nonacting units) */
      } else {
            net_prep_change_side_action(unit, unit, tmpcmdside);
      }
      return TRUE;
}

void
do_help(Side *side)
{
    /* Bring up the help window at wherever it was, if already
       created, otherwise will start at topics node. */
      show_help_window(NULL);
}

void
do_message(Side *side)
{
      message_dialog(side->prefixarg);
}

/* Dialog for the input of a textual message. */

/* (should add way to specify which sides to receive this) */

void
message_dialog(int arg)
{
      short done = FALSE, ditem;
      char *msg = NULL, *sidedesc, *nsidedesc, buf[100], buf2[100];
      SideMask sidemask;
      Side *side2;
      Str255 tmpstr;
      DialogPtr win;
      short itemtype;  Handle itemhandle;  Rect itemrect;

      if (arg < 0) {
            sidemask = ALLSIDES;
      } else {
            sidemask = NOSIDES;
            side2 = side_n(arg);
            if (side2)
              sidemask = add_side_to_set(side2, sidemask);
            else
              beep();
      }
      sidedesc = sidemask_desc(buf2, sidemask);
      strcpy(buf, sidedesc);
      c2p(buf, tmpstr);
      win = GetNewDialog(dMessage, NULL, (DialogPtr) -1L);
      GetDItem(win, diMessageTo, &itemtype, &itemhandle, &itemrect);
      SetIText(itemhandle, tmpstr);
      ShowWindow(win);
      while (!done) {
            draw_default_button(win, diMessageOK);
            SetCursor(&QD(arrow));
            ModalDialog(NULL, &ditem);
            switch (ditem) {
                  case diMessageOK:
                        GetDItem(win, diMessageText, &itemtype, &itemhandle, &itemrect);
                        msg = get_string_from_item(itemhandle);
                        GetDItem(win, diMessageTo, &itemtype, &itemhandle, &itemrect);
                        nsidedesc = get_string_from_item(itemhandle);
                        /* Fall into next case. */
                  case diMessageCancel:
                        done = TRUE;
                        break;
            }
      }
      /* Close down the dialog (*before* executing any command). */
      DisposeDialog(win);
      update_all_map_windows();
      /* Now send the message (if it wasn't cancelled) */
      if (msg != NULL && nsidedesc != NULL) {
            /* (should parse nsidedesc and use) */
            net_send_message(dside, sidemask, msg);
      }
}

void
do_move_to(Side *side)
{
    notify(dside, "Click on location to which you want to move.");
      query_position_modally(MOVE_TO_MODAL);
}

int
do_move_to_command()
{
      int x, y, dir;
      Map *map;

      if (get_a_position(&map, &x, &y, &dir)) {
            tmpcmdx = x;  tmpcmdy = y;
            apply_to_all_selected(do_one_move_to, TRUE);
            return TRUE;
      }
      return FALSE;
}

static int
do_one_move_to(Unit *unit)
{
#ifdef DESIGNERS
      if (dside->designer) {
            net_designer_teleport(unit, tmpcmdx, tmpcmdy, NULL);
            return TRUE;
      }
#endif /* DESIGNERS */
      net_set_move_to_task(unit, tmpcmdx, tmpcmdy, 0);
      return TRUE;
}

void
do_name(Side *side)
{
      apply_to_all_selected(do_one_set_name, TRUE);
}

/* Unit naming/renaming. */

int
do_one_set_name(Unit *unit)
{
      return unit_rename_dialog(unit);
}

int
unit_rename_dialog(Unit *unit)
{
      short done = FALSE, ditem;
      char *newname;
      char *namer = unit_namer(unit);
      Str255 tmpstr;
      DialogPtr win;
      short itemtype;  Handle itemhandle;  Rect itemrect;

      if (unit == NULL)
        return FALSE;
      win = GetNewDialog(dRename, NULL, (DialogPtr) -1L);
      /* Seed the text item with the original name. */
      newname = unit->name;
      if (newname == NULL)
        newname = "";
      GetDItem(win, diRenameName, &itemtype, &itemhandle, &itemrect);
      c2p(newname, tmpstr);
      SetIText(itemhandle, tmpstr);
      /* Gray out the random renaming button if no namers available. */
      GetDItem(win, diRenameRandom, &itemtype, &itemhandle, &itemrect);
      HiliteControl((ControlHandle) itemhandle, (!empty_string(namer) ? 0 : 255));
      ShowWindow(win);
      while (!done) {
            draw_default_button(win, diRenameOK);
            SetCursor(&QD(arrow));
            ModalDialog(NULL, &ditem);
            switch (ditem) {
                  case diRenameOK:
                        GetDItem(win, diRenameName, &itemtype, &itemhandle, &itemrect);
                        net_set_unit_name(dside, unit, get_string_from_item(itemhandle));
                        /* Fall into the next case. */
                  case diRenameCancel:
                        done = TRUE;
                        break;
                  case diRenameRandom:
                        newname = propose_unit_name(unit);
                        if (!empty_string(newname)) {
                              GetDItem(win, diRenameName, &itemtype, &itemhandle, &itemrect);
                              c2p(newname, tmpstr);
                              SetIText(itemhandle, tmpstr);
                        }
                        break;
            }
      }
      DisposeDialog(win);
      return TRUE;
}

int
do_one_occupant(Unit *unit)
{
      Unit *nextocc;

      nextocc = find_next_occupant(unit);
      if (nextocc != unit) {
            if (frontmap) {
                  unselect_unit_on_map(frontmap, unit);
                  select_unit_on_map(frontmap, nextocc);
                  /* Overkill, but draw_row alone not as desirable? */
                  update_cell_display(dside, unit->x, unit->y, UPDATE_ALWAYS);
            }
      }
      return TRUE;
}

void
do_occupant(Side *side)
{
      apply_to_all_selected(do_one_occupant, TRUE);
}

int other_command_prefixarg;

void
do_other(Side *side)
{
      /* Don't allow recursion with this command. */
      if (!doingother) {
            doingother = TRUE;
            other_command_prefixarg = side->prefixarg;
            show_command_window();
            other_command_prefixarg = -1;
            doingother = FALSE;
      } else {
            beep();
      }
}

/* Dialog for the input of a textual command. */

WindowPtr commandwin;

TEHandle command_text = nil;

Rect commandtextrect;

void
show_command_window()
{
      if (commandwin == nil) {
            create_command_window();
      }
      SelectTheWindow(commandwin);
      ActivateWindow(commandwin, true);
}

void
create_command_window()
{
      Rect tmprect;

      if (hasColorQD) {
            commandwin = GetNewCWindow(wCommand, NULL, NULL);
      } else {
            commandwin = GetNewWindow(wCommand, NULL, NULL);
      }
      SetPort(commandwin);
      tmprect = commandwin->portRect;
      commandtextrect = tmprect;
      commandtextrect.bottom -= 14;
      InsetRect(&commandtextrect, 5, 5);
      /* Create and clear the TextEdit record. */
      command_text = TENew(&commandtextrect, &commandtextrect);
      TESetSelect(0, 32767, command_text);
      TEDelete(command_text);
      /* Seed the command buffer with a prefix arg if was supplied. */
      if (other_command_prefixarg >= 0) {
            sprintf(spbuf, "%d ", other_command_prefixarg);
            TEInsert(spbuf, strlen(spbuf), command_text);
      }
      /* Finally make it floating. */
      MakeFloat(commandwin);
}

void
draw_command()
{
      Rect tmprect;

      MoveTo(5, 34);
      TextFont(small_font_id);
      TextSize(small_font_size);
      DrawString("\pReturn executes the command. Escape just closes the window.");
      TEUpdate(&(commandwin->portRect), command_text);
      TESetSelect(0, 32767, command_text);
      tmprect = commandtextrect;
      InsetRect(&tmprect, -1, -1);
      FrameRect(&tmprect);
}

void
activate_command(int activate)
{
      if (activate)
        TEActivate(command_text);
      else
        TEDeactivate(command_text);
}

int
do_key_down_command(int keyCode, int charCode)
{
      /* Return and Enter executes the command and closes
      the window */
      if (charCode == 13 || charCode == 3) {
            get_command_and_do();
            close_window(commandwin);
      /* Escape key just closes the window. */
      } else if (charCode == 27) {
            close_window(commandwin);
      /* Return FALSE if this is not a normal keypad key. */
      }else if (keyCode > 0x3E) {
          return FALSE;
      /* Else feed char to command text field. */
      } else {
            TEKey(charCode, command_text);
      }
      return TRUE;
}

void
do_mouse_down_command(Point mouse, int mods)
{
      if (PtInRect(mouse, &commandtextrect))
            TEClick(mouse, mods, command_text);
}

static void
get_command_and_do()
{
      int len;
      char buffer[BUFSIZE];
      CharsHandle text;

      text = TEGetText(command_text);
      len = min((*command_text)->teLength, BUFSIZE);
      strncpy(buffer, *text, len);
      buffer[len] = '\0';
      if (!empty_string(buffer)) {
            execute_long_command(dside, buffer);
      } else {
            notify(dside, "No command.");
            beep();
      }
}

void
do_print_view(Side *side)
{
      dump_ps_view(dside, NULL, "View PS");
}

static void unit_do_produce_2(Unit *unit);

void
do_produce(Side *side)
{
      int i;
      List *list;  
      UnitCloseup *closeup;
      Unit *unit;

      /* Try different alternatives to find a unit. */
      list = list_from_window(topWindow);
      if (list != NULL) {
            unit = selected_unit_in_list(list);
            if (unit != NULL && can_produce(unit)) {
                  unit_do_produce_2(unit);
                  return;
            }
            return;
      }
      closeup = unit_closeup_from_window(topFloat);
      if (closeup != NULL) {
            unit = closeup->unit;
            if (unit != NULL && can_produce(unit)) {
                  unit_do_produce_2(unit);
                  return;
            }
            return;
      }
      if (frontmap) {
            for (i = 0; i < frontmap->numselections; ++i) {
                  unit = frontmap->selections[i];
                  if (unit != NULL && can_produce(unit)) {
                        unit_do_produce_2(unit);
                        return;
                  }
            }
            return;
      }
      /* No way to figure out the unit to be producing with, so complain. */
      beep();
}

static void
unit_do_produce_2(Unit *unit)
{
      int m, n;

    n = 9999;
    if (dside->prefixarg > 0)
        n = dside->prefixarg;
      for_all_material_types(m) {
            if (um_acp_to_produce(unit->type, m) > 0) {
                  net_push_produce_task(unit, m, n);
                  return;
            }
      }
}

void
do_quit(Side *side)
{
      quit_the_game();
}

static int allsumx, allsumy, unitcount;

int
add_unit_position(Unit *unit)
{
      allsumx += unit->x;  allsumy += unit->y;
      ++unitcount;
      return TRUE;
}

void
do_recenter(Side *side)
{
      int avgx, avgy;

      if (frontmap) {
            allsumx = allsumy = 0;
            unitcount = 0;
            apply_to_all_selected(add_unit_position, FALSE);
            if (unitcount == 0) {
                  beep();
                  return;
            }
            avgx = allsumx / unitcount;  avgy = allsumy / unitcount;
            set_map_focus(frontmap, avgx, avgy);
      }
}

/* Recalculate and redraw everything. */

void
do_refresh(Side *side)
{
      Map *map;
      List *list;
      UnitCloseup *closeup;

      reset_coverage();
      reset_all_views();
      compute_all_feature_centroids();
      /* Force updates to all open windows. */
      force_update(gamewin);
      force_update(noticewin);
      force_update(historywin);
      force_update(constructionwin);
      force_update(helpwin);
      for_all_maps(map) {
            force_update(map->window);
      }
      for_all_lists(list) {
            force_update(list->window);
      }
      for_all_unit_closeups(closeup) {
            force_update(closeup->window);
      }
}

void
do_remove_terrain(Side *side)
{
    int x, y, dir;
      Map *map;
      
      if (get_a_position(&map, &x, &y, &dir)) {
            tmpcmdx = x;  tmpcmdy = y;  tmpcmddir = dir;
            apply_to_all_selected(do_one_remove_terrain, TRUE);
            return;
      }
      beep();
}

static int
do_one_remove_terrain(Unit *unit)
{
      int u, t, x, y, dir;

      u = unit->type;
      for_all_terrain_types(t) {
            if (ut_acp_to_remove_terrain(u, t) > 0
                  && unit->act
                && unit->act->acp >= ut_acp_to_remove_terrain(u, t)) {
                if (distance(tmpcmdx, tmpcmdy, unit->x, unit->y) <= ut_alter_range(u, t)) {
                        x = tmpcmdx;  y = tmpcmdy;
                        dir = tmpcmddir;
                  } else {
                        x = unit->x;  y = unit->y;
                        dir = approx_dir(tmpcmdx - unit->x, tmpcmdy - unit->y);
                  }
                  if (valid(check_remove_terrain_action(unit, unit, x, y, dir, t))) {
                        if (net_prep_remove_terrain_action(unit, unit, x, y, dir, t))
                          return TRUE;
                  }
            }
      }
      return FALSE;
}

void
do_repair(Side *side)
{
      Map *map;
      
      if (get_a_unit(&map, &tmpcmdunit)) {
            apply_to_all_selected(do_one_repair, TRUE);
            return;
      }
      beep();
}

static int
do_one_repair(Unit *unit)
{
      int i;
      Unit *other;

      other = tmpcmdunit;
      /* If no unit designated, assume self-repair desired. */
      if (tmpcmdunit == NULL)
        other = unit;
      if (other != NULL
            && other->side == unit->side
            && valid(check_repair_action(unit, unit, other))) {
            net_prep_repair_action(unit, unit, other);
            return TRUE;
      }
      return FALSE;
}

void
do_resign(Side *side)
{
      if (endofgame) {
            notify(side, "Game is already over.");
            beep();
      } else if (!side->ingame) {
            notify(side, "You are already out of the game.");
            beep();
      } else if (CautionAlert(aConfirmResign, nil) == aiConfirmResignResign) {
            net_resign_game(side, NULL);
      }
}

void
do_save(Side *side)
{
      save_the_game(FALSE, FALSE);
}

void
do_set_formation(Side *side)
{
      int i, numcould = 0, numnot = 0;
      Map *map;
      Unit *follower, *leader;
      
      if (get_a_unit(&map, &leader)) {
            if (leader != NULL) {
                  for (i = 0; i < map->numselections; ++i) {
                        if ((follower = map->selections[i]) != NULL && valid_selection(follower)) {
                              if (leader != follower
                                    && leader->side == follower->side
                                    ) {
                                    net_set_formation(follower, leader, follower->x - leader->x, follower->y - leader->y, 1, 1);
                                    ++numcould;
                              } else {
                                    ++numnot;
                              }
                        }
                  }
            } else {
                  /* Can't make a formation without a leader. */
                  cmd_error(dside, "no leader found");
            }
      }
      /* If nobody could do the command, beep once. */
      if (numcould == 0 && numnot > 0) {
            beep();
      }
}

void
do_set_view_angle(Side *side)
{
      int angle;

      if (frontmap) {
            angle = frontmap->vp->angle;
            if (angle == 90)
              angle = 30;
            else if (angle == 30)
              angle = 15;
            else
              angle = 90;
            /* A suitable vertscale is now computed by set_map_angle. 
            Only override it if provided with a valid prefixarg. */
            set_map_angle(frontmap, angle);
            frontmap->vp->vertscale 
               = (side->prefixarg < 1 ? frontmap->vp->vertscale : side->prefixarg);
      } else {
            beep();
      }
}

void
do_standing_orders(Side *side)
{
      int rslt;

      if (cmdargstr) {
            rslt = parse_standing_order(dside, cmdargstr);
            if (rslt < 0)
              beep();
            return;
      }
      beep();
}

void 
do_survey(Side *side)
{
      if (frontmap) {
            toggle_survey(frontmap);
      } else {
            beep();
      }
}

void
do_up(Side *side)
{
      int i, numcould = 0, numnot = 0, rawamt = 1;
      int amt, newalt;
      Point target;
      Unit *unit;

      if (frontmap) {
            for (i = 0; i < frontmap->numselections; ++i) {
                  if ((unit = frontmap->selections[i]) != NULL 
                         && valid_selection(unit)) {
                        amt = rawamt;
                        newalt = (unit_alt(unit) + amt) << 1;
                        if (valid(check_move_action(unit, unit, unit->x, unit->y, newalt))) {
                              net_prep_move_action(unit, unit, unit->x, unit->y, newalt);
                              ++numcould;
                        } else {
                              ++numnot;
                        }
                  }
            }
      }
      /* If nobody could do the action, beep once. */
      if (numcould == 0 && numnot > 0) {
            beep();
      }
}

#if 0       /* Not supported in the kernel yet. */

void
do_down(Side *side)
{
      int i, numcould = 0, numnot = 0, rawamt = 0;
      int amt, newalt;
      Point target;
      Unit *unit;

      rawamt = 0; 
      if (frontmap) {
            for (i = 0; i < frontmap->numselections; ++i) {
                  if ((unit = frontmap->selections[i]) != NULL 
                         && valid_selection(unit)) {
                        amt = rawamt;
                        if (amt == 0 && unit_alt(unit) > 0)
                          amt = unit_alt(unit) / 2;
                        newalt = (unit_alt(unit) - amt) << 1;
                        if (valid(check_move_action(unit, unit, unit->x, unit->y, newalt))) {
                              net_prep_move_action(unit, unit, unit->x, unit->y, newalt);
                              ++numcould;
                        } else {
                              ++numnot;
                        }
                  }
            }
      }
      /* If nobody could do the action, beep once. */
      if (numcould == 0 && numnot > 0) {
            beep();
      }
}

#endif

void
do_version(Side *side)
{
      do_about_box();
}

void
do_warranty(Side *side)
{
      show_help_window(warranty_help_node);
}

void
do_zoom_in(Side *side)
{
      if (frontmap) {
            magnify_map(frontmap, 1);
      } else {
            beep();
      }
}

void
do_zoom_out(Side *side)
{
      if (frontmap) {
            magnify_map(frontmap, -1);
      } else {
            beep();
      }
}

/* End of alphabetized commands. */

#ifdef DESIGNERS

/* Toggle the designer mode. */

void
do_design(Side *side)
{
      if (!side->designer) {
            enable_designing(FALSE);
      } else {
            disable_designing();
      }
}

#endif

#ifdef DEBUGGING

void
do_profile(Side *side)
{
      toggle_profiling();
}

void
do_trace(Side *side)
{
      toggle_profiling();

#ifdef PROFILING

#ifdef THINK_C                /* Not used by CodeWarrior. */

      _trace = 1;

#endif /* THINK_C */

#endif /* PROFILING */

}

void
toggle_profiling()
{

#ifdef PROFILING        

#ifdef THINK_C                /* Not used by CodeWarrior. */

      extern int _profile;

#endif /* THINK_C */

      /* Only toggle Profile if profiling is enabled! */
      Profile = !Profile;

      /* Necessary to update game window with the
      new profiling status. */
      draw_game();

#ifdef THINK_C

      if (Profile && !_profile) {
            InitProfile(1000, 100);
            freopen("Xconq.ProfileOut", "w", stdout);
      }
      if (!Profile && _profile) {
            DumpProfile();
            fflush(stdout);
      }

#endif /* THINK_C */

#if __profile__               /* CodeWarrior support. */

      if (Profile && ProfilerGetStatus() == false) {
            ProfilerSetStatus(true);
      }
      if (!Profile && ProfilerGetStatus() == true) {
            ProfilerSetStatus(false);
            ProfilerDump("\pXconq.Profile");
            ProfilerClear();
      }

#endif /* __profile__ */

#endif /* PROFILING */

}

#endif /* DEBUGGING */

/* Generic command error feedback. */

void
cmd_error(Side *side, char *fmt, ...)
{
      va_list ap;

      if (!empty_string(fmt)) {
            va_start(ap, fmt);
      vnotify(side, fmt, ap);
            va_end(ap);
      }
    /* (should) Only beep once, even if a command generates multiple error messages. */
    beep();
}

Generated by  Doxygen 1.6.0   Back to index