+++ /dev/null
-/* Handling of assorted minor windows for the Mac interface to Xconq.
- Copyright (C) 1992-1999 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 "macconq.h"
-
-#define unit_doctrine(unit) \
- (unit->side->udoctrine[unit->type])
-
-#define DEFAULT_RUN (99)
-
-static void create_game_window(void);
-static void draw_game_side(Side *side2);
-static int feeling_towards(Side *side, Side *side2);
-
-static void create_construction_window(void);
-static void init_construction_lists(void);
-static void reinit_construction_lists(void);
-static void draw_construction_default(void);
-static void calc_construction_rects(void);
-static Unit *get_selected_construction_unit(void);
-static int get_selected_construction_type(void);
-static int get_selected_construction_advance(void);
-static void select_advance_in_construction_window(int a);
-static void maybe_add_unit_to_construction_list(Unit *unit);
-static void update_unit_list_for_type(int u);
-static void update_unit_list_for_advance(int a);
-static void update_type_list_for_unit(Unit *unit);
-static void update_construction_advance_list(void);
-static void update_advance_list_for_unit(Unit *unit);
-static void adjust_construction_controls(void);
-static void adjust_construction_items(void);
-
-static void hit_research_dialog(int ditem);
-
-static void create_history_window(void);
-static void calc_history_layout(void);
-static void set_history_scrollbar(void);
-static void draw_historical(HistEvent *hevt, int y, int drawevt);
-static pascal void history_scroll_fn(ControlHandle control, short code);
-static void move_history_scrollbar(int h, int v);
-
-static void create_notice_window(void);
-static void adjust_notice_scrollbar(void);
-static pascal void notice_vscroll_fn(ControlHandle control, short code);
-
-static void create_scores_window(void);
-static void append_scores(char *str);
-static void adjust_scores_scrollbar(void);
-static pascal void scores_vscroll_fn(ControlHandle control, short code);
-
-/* Globals for the research window. */
-
-WindowPtr researchwin = nil;
-
-/* Globals for the game window. */
-
-WindowPtr gamewin = nil;
-
-int gamewinw = 160;
-int gamedatehgt = 18;
-int gameclockoffset;
-int gameclockhgt = 15;
-int gamenoteoffset;
-int gamenotehgt = 15;
-int gametophgt;
-
-int gamesidehgt = 24;
-int gamesideclockhgt = 15;
-int gamesideclockoffset;
-int gamesidescorehgt = 15;
-int gamesidescoreoffset;
-
-int gamenumsides;
-
-Handle aisicnhandle = nil;
-Handle facesicnhandle[3];
-
-char *game_progress_str = "";
-
-time_t lastnow;
-
-/* Globals for the construction window. */
-
-WindowPtr constructionwin = nil;
-
-static ListHandle construction_unit_list = nil;
-static ListHandle construction_type_list = nil;
-static ListHandle construction_advance_list = nil;
-
-static int maxtypewid;
-static int constructmargin = 5;
-static int constructtop = 32;
-
-/* This is the vector of units that can do construction or development. */
-
-static UnitVector *constructor_units = NULL;
-static UnitVector *research_units = NULL;
-
-static int numposstypes;
-static int *possibletypes = NULL;
-
-static int numpossadvances;
-static int *possibleadvances = NULL;
-
-int currunlength;
-
-int editedrunlength = -1;
-
-/* (this is referenced from the end-turn command, so can't make static) */
-ControlHandle constructbutton;
-ControlHandle researchbutton;
-static ControlHandle developbutton;
-
-TEHandle run_length_text = nil;
-
-static Rect runlengthrect;
-static Rect unitlistrect;
-static Rect typelistrect;
-static Rect advancelistrect;
-
-/* Globals for the history window. */
-
-WindowPtr historywin = nil;
-
-int maxvishistlines = 200;
-
-HistEvent **histcontents = NULL;
-
-int numhistcontents = 0;
-
-ControlHandle histvscrollbar;
-
-int history_line_spacing;
-
-int numvishistlines;
-
-int total_history_lines = 0;
-
-ControlActionUPP history_scroll_proc;
-
-/* Globals for the notice window. */
-
-DialogPtr noticewin = nil;
-
-static TEHandle notice_text = nil;
-
-static ControlHandle notice_v_scrollbar;
-
-ControlActionUPP notice_vscroll_proc;
-
-static TextStyle *noticeStyle;
-
-/* Globals for the scores window. */
-
-DialogPtr scoreswin = nil;
-
-static TEHandle scores_text = nil;
-
-static ControlHandle scores_v_scrollbar;
-
-ControlActionUPP scores_vscroll_proc;
-
-/* The game progress window. */
-
-/* This is the top-level access to bring up the game window, can be called
- anywhere, anytime. */
-
-void
-show_game_window()
-{
- if (gamewin == nil) {
- create_game_window();
- }
- SelectTheWindow(gamewin);
- ActivateWindow(gamewin, true);
-}
-
-/* Create the game progress window. */
-
-void
-create_game_window()
-{
- int screenwidth;
- extern int numscores;
-
- /* Create the window, color if possible, since emblems may be in color. */
- if (hasColorQD) {
- gamewin = GetNewCWindow(wFloatFixed, NULL, NULL);
- } else {
- gamewin = GetNewWindow(wFloatFixed, NULL, NULL);
- }
- SetWTitle(gamewin, "\pGame");
- gametophgt = gamedatehgt;
- if (g_rt_per_turn() > 0 || g_rt_for_game() > 0) {
- gameclockoffset = gametophgt;
- gametophgt += gameclockhgt;
- }
- gamenoteoffset = gametophgt;
- gametophgt += gamenotehgt;
- /* Add some space if sides have a per-turn and/or per-game clock. */
- if (g_rt_per_side() > 0) {
- gamesideclockoffset = gamesidehgt;
- gamesidehgt += gamesideclockhgt;
- }
- /* Add additional space for each two scorekeepers. */
- if (keeping_score()) {
- gamesidescoreoffset = gamesidehgt;
- gamesidehgt += gamesidescorehgt * ((numscorekeepers + 1) / 2);
- }
- /* This is not growable, so we have to ensure it's big enough to start with. */
- /* (Record the current numsides so we can grow the window later.) */
- if (side_has_ai(indepside) || side_has_display(indepside)) {
- gamenumsides = numtotsides;
- } else {
- gamenumsides = numsides;
- }
- SizeWindow(gamewin, gamewinw, gametophgt + gamenumsides * gamesidehgt, 1);
- if (first_windows) {
- get_main_screen_size(&screenwidth, NULL);
- /* Tweaked to fit Apple Platinum theme. */
- MoveWindow(gamewin, screenwidth - gamewinw - 3, 41 + 15, FALSE);
- }
- /* Get handles to useful sicns. */
- aisicnhandle = GetNamedResource('SICN', "\pmplayer");
- facesicnhandle[0] = GetNamedResource('SICN', "\phostile");
- facesicnhandle[1] = GetNamedResource('SICN', "\pneutral");
- facesicnhandle[2] = GetNamedResource('SICN', "\pfriendly");
-
- /* Finally make it floating. */
- MakeFloat(gamewin);
-}
-
-char *last_status;
-char *last_status_left;
-char *last_status_resv;
-char *last_status_fini;
-char **last_status_score1;
-
-void
-draw_game()
-{
- Side *side2;
- GrafPtr oldport;
- int newnumsides = 0;
-
- if (gamewin == nil)
- return;
- if (side_has_ai(indepside) || side_has_display(indepside)) {
- newnumsides = numtotsides;
- } else {
- newnumsides = numsides;
- }
- /* The window might need to get bigger. */
- if (newnumsides != gamenumsides) {
- last_status = NULL;
- last_status_left = NULL;
- last_status_resv = NULL;
- last_status_fini = NULL;
- last_status_score1 = NULL;
- gamenumsides = newnumsides;
- SizeWindow(gamewin, gamewinw, gametophgt + gamenumsides * gamesidehgt, 1);
- }
- if (last_status == NULL)
- last_status = xmalloc(numsides + 1);
- if (last_status_left == NULL)
- last_status_left = xmalloc(numsides + 1);
- if (last_status_resv == NULL)
- last_status_resv = xmalloc(numsides + 1);
- if (last_status_fini == NULL)
- last_status_fini = xmalloc(numsides + 1);
- if (last_status_score1 == NULL) {
- int i;
- last_status_score1 = (char **) xmalloc((numtotsides + 1) * sizeof(char *));
- for (i = 0; i <= numtotsides; ++i)
- last_status_score1[i] = xmalloc(100);
- }
- GetPort(&oldport);
- SetPort(gamewin);
- TextFont(large_font_id);
- TextSize(large_font_size);
- if (endofgame)
- RGBForeColor(&graycolor);
- draw_game_date();
- draw_game_progress();
- /* Draw a solid separating line between date info and side list. */
- RGBForeColor(<graycolor);
- MoveTo(0, gametophgt);
- Line(gamewinw, 0);
- ForeColor(blackColor);
- for_all_sides(side2) {
- draw_game_side(side2);
- }
- SetPort(oldport);
-}
-
-/* Display the current time and date and any realtime countdowns. */
-
-void
-draw_game_date()
-{
- Rect tmprect;
-
- SetRect(&tmprect, 0, 0, gamewinw, gamedatehgt - 1);
- EraseRect(&tmprect);
- MoveTo(tmprect.left + 10, tmprect.top + 12);
- TextFace(bold);
- DrawText(curdatestr, 0, strlen(curdatestr));
- TextFace(0);
- draw_game_clocks();
-#ifdef DEBUGGING
- /* Indicate the state of all the debug flags (and profiling). */
- if (Debug || DebugM || DebugG || Profile) {
- sprintf(spbuf, "%c%c%c%c",
- (Debug ? 'D' : ' '), (DebugM ? 'M' : ' '), (DebugG ? 'G' : ' '),
- (Profile ? 'P' : ' '));
- MoveTo(tmprect.right - 40, tmprect.top + 12);
- DrawText(spbuf, 0, strlen(spbuf));
- }
-#endif /* DEBUGGING */
-}
-
-void
-draw_game_clocks()
-{
- int elapsed, s2, sy;
- time_t now;
- Rect tmprect;
- Side *side2;
-
- /* Draw per-turn and per-game time limits that for the game as a whole. */
- SetRect(&tmprect, 0, gamedatehgt, gamewinw / 2, gamedatehgt + gameclockhgt - 1);
- if (g_rt_per_turn() > 0) {
- time(&now);
- elapsed = (int) difftime(now, turn_play_start_in_real_time);
- time_desc(spbuf, g_rt_per_turn() - elapsed, g_rt_per_turn());
- EraseRect(&tmprect);
- MoveTo(tmprect.left + 20, tmprect.top + 10);
- DrawText(spbuf, 0, strlen(spbuf));
- lastnow = now;
- }
- OffsetRect(&tmprect, 100, 0);
- if (g_rt_for_game() > 0) {
- time(&now);
- elapsed = (int) difftime(now, game_start_in_real_time);
- time_desc(spbuf, g_rt_for_game() - elapsed, g_rt_for_game());
- EraseRect(&tmprect);
- MoveTo(tmprect.left + 10, tmprect.top + 10);
- DrawText(spbuf, 0, strlen(spbuf));
- lastnow = now;
- }
- /* Draw per-side clocks if any limits defined. */
- if (g_rt_per_side() > 0) {
- for_all_sides(side2) {
- if (side2->ingame
- && (side_has_ai(side2) || side_has_display(side2))) {
- s2 = side_number(side2);
- if (side_has_ai(indepside) || side_has_display(indepside))
- ++s2;
- sy = gametophgt + (s2 - 1) * gamesidehgt + gamesideclockoffset;
- elapsed = 0;
- if (!side2->finishedturn)
- /* should be side start */
- elapsed = (int) difftime(now, turn_play_start_in_real_time);
- time_desc(spbuf, g_rt_per_side() - side2->totaltimeused - elapsed, g_rt_per_side());
- SetRect(&tmprect, 0, sy, gamewinw, sy + gamesideclockhgt - 1);
- EraseRect(&tmprect);
- MoveTo(tmprect.left + 20, tmprect.top + 10);
- DrawText(spbuf, 0, strlen(spbuf));
- /* (should draw per-turn side usage) */
- }
- }
- }
-}
-
-void
-draw_game_progress()
-{
- Rect tmprect;
-
- SetRect(&tmprect, 0, gamenoteoffset, gamewinw, gamenoteoffset + gamenotehgt - 1);
- EraseRect(&tmprect);
- MoveTo(23, gamenoteoffset + 12);
- DrawText(game_progress_str, 0, strlen(game_progress_str));
-}
-
-/* Draw info about a given side. */
-
-void
-draw_game_side(Side *side2)
-{
- int s2 = side_number(side2);
- int sx = 23, sy;
-
- if (inactive_indepside(side2)) {
- return;
- } else if (side_has_ai(indepside) || side_has_display(indepside)) {
- ++s2;
- }
- sy = gametophgt + (s2 - 1) * gamesidehgt;
- draw_side_emblem(gamewin, 2, sy + 4, 16, 16, side_number(side2), shadow_emblem);
- strcpy(spbuf, short_side_title(side2));
- MoveTo(sx, sy + 13);
- /* Put the name of our side in boldface. */
- TextFace((side2 == dside ? bold : 0));
- if (!side2->ingame || endofgame)
- RGBForeColor(&graycolor);
- DrawText(spbuf, 0, strlen(spbuf));
- TextFace(0);
- if (side_has_ai(side2)) {
- /* Show that the side is run by an AI. */
- plot_sicn(gamewin, 142, sy + 2, aisicnhandle, 0, TRUE, srcOr);
- }
- if (side2 != dside
- && (side_has_ai(side2) || side_has_display(side2))) {
- /* Indicate attitude of other side. */
- plot_sicn(gamewin, 126, sy + 2,
- facesicnhandle[feeling_towards(side2, dside)], 0, TRUE, srcOr);
- }
- ForeColor(blackColor);
- last_status[s2] = -1;
- last_status_left[s2] = -1;
- last_status_resv[s2] = -1;
- last_status_fini[s2] = -1;
- *(last_status_score1[s2]) = '\0';
- draw_side_status(side2);
- /* Draw a separating line. */
- RGBForeColor(<graycolor);
- MoveTo(0, sy + gamesidehgt);
- Line(gamewinw, 0);
- ForeColor(blackColor);
-}
-
-/* (should make this more generic) */
-
-int
-feeling_towards(Side *side, Side *side2)
-{
- if (trusted_side(side2, side)) {
- return 2;
- } else if (side_has_ai(side) && should_try_to_win(side)) {
- return 0;
- } else {
- return 1;
- }
-}
-
-/* Draw the current details about a side. */
-
-void
-draw_side_status(Side *side2)
-{
- int s2 = side_number(side2);
- int sx, sy, i;
- int totacp, resvacp, acpleft, percentleft, percentresv;
- int newstatus;
- char *scoredesc;
- Rect siderect, tmprect, progressrect;
- RGBColor tmpcolor;
- Scorekeeper *sk;
- extern int curpriority;
-
- if (side_has_ai(indepside) || side_has_display(indepside))
- ++s2;
- /* Be safe. It's probably not great to be passing through here before the game
- window is actually set up, but it's easier to just ignore the attempt than
- to figure out why it's attempting... */
- if (last_status == NULL)
- return;
- /* If this is the first time we draw a side that lost, we also want to redraw the
- name etc. so that they are grayed out. The test for last_status[s2] != -1 is to
- prevent an infinite loop. */
- if (!side2->ingame
- && last_status[s2] != 3 && last_status[s2] != -1) {
- draw_game_side(side2);
- return;
- }
- sy = gametophgt + (s2 - 1) * gamesidehgt;
- newstatus = last_status[s2];
- percentleft = 0;
- SetRect(&siderect, 0, sy + 1, gamewinw, sy + gamesidehgt);
- /* Set up the area where we show progress. */
- SetRect(&progressrect, 24, sy + 13 + 4, 24 + 100, sy + 13 + 4 + 7);
- if (!side2->ingame || endofgame) {
- /* last_status == 3 now means that the side is out of the game. */
- if (last_status[s2] != 3) {
- if (side_won(side2)) {
- /* should indicate that this side has won. */
- /* draw like a trophy or flourishes or some such? */
- } else if (side_lost(side2)) {
- /* Draw a (solid) line crossing out the loser. Simple and obvious. */
- tmpcolor.red = 0xFFFF;
- tmpcolor.green = 0;
- tmpcolor.blue = 0;
- RGBForeColor(&tmpcolor);
- PenSize(2,2);
- MoveTo(1, sy + 8);
- Line(gamewin->portRect.right - 3, 0);
- ForeColor(blackColor);
- PenNormal();
- }
- newstatus = 3;
- }
-#ifdef DESIGNERS
- } else if (numdesigners > 0) {
- if (side2->ingame && last_status[s2] != 0) {
- tmprect = progressrect;
- EraseRect(&tmprect);
- newstatus = 0;
- }
-#endif /* DESIGNERS */
- } else {
- if (!g_use_side_priority() || curpriority == side2->priority) {
- /* Show the current acp totals/progress of the side. */
- /* This is not quite the security hole it might seem,
- you don't get much advantage out of seeing how far along each side is,
- and it gives you a feel for how the turn is progressing. */
- totacp = side_initacp(side2);
- if (totacp > 0) {
- acpleft = side_acp(side2);
- resvacp = side_acp_reserved(side2);
- if (totacp > 0) {
- percentleft = (100 * acpleft) / totacp;
- percentleft = max(0, min(99, percentleft));
- percentresv = (100 * resvacp) / totacp;
- /* Acp in reserve should be less than acp total. */
- percentresv = max(0, min(percentleft, percentresv));
- } else {
- percentleft = percentresv = 0;
- }
- /* Only draw if there's been any actual change. */
- if (last_status[s2] != 1
- || last_status_left[s2] != percentleft
- || last_status_resv[s2] != percentresv) {
- if (percentleft > 0) {
- tmprect = progressrect;
- InsetRect(&tmprect, 1, 1);
- EraseRect(&tmprect);
- tmprect.right = tmprect.left + percentleft - 1;
- tmpcolor.red = 0;
- tmpcolor.green = 0xFFFF;
- tmpcolor.blue = 0;
- RGBForeColor(&tmpcolor);
- FillRect(&tmprect, QDPat(black));
- ForeColor(blackColor);
- }
- if (percentresv > 0) {
- tmprect = progressrect;
- InsetRect(&tmprect, 1, 1);
- tmprect.right = tmprect.left + percentresv - 1;
- tmpcolor.red = 0xFFFF;
- tmpcolor.green = 0;
- tmpcolor.blue = 0xFFFF;
- RGBForeColor(&tmpcolor);
- FillRect(&tmprect, QDPat(black));
- ForeColor(blackColor);
- }
- last_status_left[s2] = percentleft;
- last_status_resv[s2] = percentresv;
- }
- newstatus = 1;
- } else {
- if (last_status[s2] != 2) {
- tmprect = progressrect;
- InsetRect(&tmprect, 1, 1);
- EraseRect(&tmprect);
- newstatus = 2;
- }
- }
- } else if (g_use_side_priority() && curpriority != side2->priority) {
- newstatus = 0;
- }
- /* (should this be a generic kernel test?) */
- if (side2->finishedturn || !(side_has_ai(side2) || side_has_display(side2))) {
- if (last_status_fini[s2] != 1) {
- tmprect = progressrect;
- InsetRect(&tmprect, 1, 1);
- EraseRect(&tmprect);
- tmpcolor.red = 0xFFFF;
- tmpcolor.green = 0xA000;
- tmpcolor.blue = 0xFFFF;
- RGBForeColor(&tmpcolor);
- tmprect.right = tmprect.left + percentleft - 1;
- FillRect(&tmprect, QDPat(black));
- ForeColor(blackColor);
- last_status_fini[s2] = 1;
- }
- } else if (!side2->finishedturn) {
- last_status_fini[s2] = 0;
- }
- }
- /* Decide how to frame the progress bar - each shade indicates something. */
- if (newstatus != last_status[s2]) {
- if (newstatus == 0 || newstatus == 3) {
- EraseRect(&progressrect);
- PenPat(QDPat(white));
- } else if (/*newstatus == */1) {
- PenPat(QDPat(black));
- } else if (newstatus == 2) {
- PenPat(QDPat(gray));
- } else {
- PenPat(QDPat(ltGray));
- }
- FrameRect(&progressrect);
- PenNormal();
- last_status[s2] = newstatus;
- }
- /* Always draw the score. */
- if (keeping_score()) {
- siderect.top += gamesidescoreoffset;
- siderect.bottom = siderect.top + gamesidescorehgt - 1;
- TextFont(small_font_id);
- TextSize(small_font_size);
- if (!side2->ingame || endofgame)
- RGBForeColor(&graycolor);
- i = 0;
- for_all_scorekeepers(sk) {
- scoredesc = side_score_desc(spbuf, side2, sk);
- if ((i == 0 && strcmp(scoredesc, last_status_score1[s2]) != 0)
- || i > 0) {
- if ((i & 1) == 0)
- EraseRect(&siderect);
- /* Draw two scorekeepers per line. */
- sx = (((i & 1) == 1) ? gamewinw / 2 : 0);
- /* Draw the scorekeeper's status. */
- MoveTo(sx + 24, siderect.top + 10);
- DrawText(scoredesc, 0, strlen(scoredesc));
- if (i == 0)
- strcpy(last_status_score1[s2], scoredesc);
- }
- ++i;
- /* Offset rectangle to next row. */
- if ((i & 1) == 0)
- OffsetRect(&siderect, 0, gamesidescorehgt);
- }
- TextFont(large_font_id);
- TextSize(large_font_size);
- ForeColor(blackColor);
- }
-}
-
-void
-do_mouse_down_game(Point mouse, int mods)
-{
- beep();
-}
-
-/* Create and/or bring up the construction planning window. */
-
-void
-show_construction_window()
-{
- if (constructionwin == nil) {
- create_construction_window();
- } else {
- reinit_construction_lists();
- }
- SelectTheWindow(constructionwin);
- ActivateWindow(constructionwin, true);
-}
-
-/* The construction planning window. */
-
-void
-create_construction_window()
-{
- int done = FALSE, mainheight;
- Point cellsize;
- Rect listrect, tmprect;
-
- if (hasColorQD) {
- constructionwin = GetNewCWindow(wConstruction, NULL, NULL);
- } else {
- constructionwin = GetNewWindow(wConstruction, NULL, NULL);
- }
- constructbutton = GetNewControl(cConstructButton, constructionwin);
- developbutton = GetNewControl(cDevelopButton, constructionwin);
- researchbutton = GetNewControl(cResearchButton, constructionwin);
- SetPort(constructionwin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- calc_construction_rects();
- run_length_text = TENew(&runlengthrect, &runlengthrect);
- set_construction_run_length(DEFAULT_RUN);
- editedrunlength = -1;
- /* Set up the list of all constructing units. */
- tmprect = unitlistrect;
- tmprect.right -= sbarwid;
- SetRect(&listrect, 0, 0, 1, 0);
- SetPt(&cellsize, 300, 12);
- /* Create the list of units itself. */
- construction_unit_list =
- LNew(&tmprect, &listrect, cellsize, 128, constructionwin,
- FALSE, FALSE, FALSE, TRUE);
- /* Now set up the list of types. */
- tmprect = typelistrect;
- tmprect.right -= sbarwid;
- SetRect(&listrect, 0, 0, 1, 0);
- /* (should calc this from the desired font) */
- SetPt(&cellsize, 300, 12);
- construction_type_list =
- LNew(&tmprect, &listrect, cellsize, 128, constructionwin,
- FALSE, FALSE, FALSE, TRUE);
- /* Now set up the list of advances. */
- tmprect = advancelistrect;
- tmprect.right -= sbarwid;
- SetRect(&listrect, 0, 0, 1, 0);
- /* (should calc this from the desired font) */
- SetPt(&cellsize, 300, 12);
- construction_advance_list =
- LNew(&tmprect, &listrect, cellsize, 128, constructionwin,
- FALSE, FALSE, FALSE, TRUE);
- init_construction_lists();
- /* Finally make it floating. */
- MakeFloat(constructionwin);
-}
-
-/* Build the list of constructing units and the list of constructible types. */
-
-void
-init_construction_lists()
-{
- int a, u;
- Unit *unit;
- Cell tmpcell;
-
- /* Update the list of units. */
- LDoDraw(0, construction_unit_list);
- LDelRow(0, 0, construction_unit_list);
- SetPt(&tmpcell, 0, 0);
- /* Create the vector of constructing units, at a reasonable initial size. */
- if (constructor_units == NULL) {
- constructor_units = make_unit_vector(max(50, numunits));
- }
- clear_unit_vector(constructor_units);
- for_all_side_units(dside, unit) {
- maybe_add_unit_to_construction_list(unit);
- }
- LDoDraw(1, construction_unit_list);
- /* Update the list of types. */
- LDoDraw(0, construction_type_list);
- LDelRow(0, 0, construction_type_list);
- SetPt(&tmpcell, 0, 0);
- if (possibletypes == NULL)
- possibletypes = (int *) xmalloc(numutypes * sizeof(int));
- numposstypes = 0;
- for_all_unit_types(u) {
- if (construction_possible(u)
- && side_can_build(dside, u)) {
- LAddRow(1, tmpcell.v, construction_type_list);
- constructible_desc(spbuf, dside, u, NULL);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_type_list);
- ++tmpcell.v;
- possibletypes[numposstypes++] = u;
- }
- }
- LDoDraw(1, construction_type_list);
-
- /* Update the list of advances. */
- LDoDraw(0, construction_advance_list);
- LDelRow(0, 0, construction_advance_list);
- SetPt(&tmpcell, 0, 0);
- if (possibleadvances == NULL && numatypes > 0)
- possibleadvances = (int *) xmalloc(numatypes * sizeof(int));
- numpossadvances = 0;
- for_all_advance_types(a) {
- if (side_can_research(dside, a)) {
- LAddRow(1, tmpcell.v, construction_advance_list);
- researchible_desc(spbuf, get_selected_construction_unit(), a);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_advance_list);
- ++tmpcell.v;
- possibleadvances[numpossadvances++] = a;
- }
- }
- LDoDraw(1, construction_advance_list);
-
- adjust_construction_controls();
-}
-
-void
-reinit_construction_lists()
-{
- init_construction_lists();
-}
-
-void
-set_construction_run_length(int len)
-{
- /* Do nothing if no change. */
- if (len == currunlength)
- return;
- currunlength = len;
- TESetSelect(0, 32767, run_length_text);
- TEDelete(run_length_text);
- sprintf(tmpbuf, "%d", len);
- TEInsert(tmpbuf, strlen(tmpbuf), run_length_text);
-}
-
-/* Draw the construction window by updating the lists and framing them. */
-
-void
-draw_construction()
-{
- Rect tmprect;
-
- calc_construction_rects();
- TEUpdate(&(constructionwin->portRect), run_length_text);
- tmprect = runlengthrect;
- InsetRect(&tmprect, -1, -1);
- FrameRect(&tmprect);
- LUpdate(constructionwin->visRgn, construction_unit_list);
- tmprect = unitlistrect;
- InsetRect(&tmprect, -1, -1);
- FrameRect(&tmprect);
- LUpdate(constructionwin->visRgn, construction_type_list);
- tmprect = typelistrect;
- InsetRect(&tmprect, -1, -1);
- FrameRect(&tmprect);
- LUpdate(constructionwin->visRgn, construction_advance_list);
- tmprect = advancelistrect;
- InsetRect(&tmprect, -1, -1);
- FrameRect(&tmprect);
- /* Maybe show the construct button as the default. */
- draw_construction_default();
-}
-
-/* Draw a heavy outline around the construction button. */
-
-void
-draw_construction_default()
-{
- Rect tmprect;
- GrafPtr oldport;
-
- GetPort(&oldport);
- SetPort(constructionwin);
- tmprect = (*constructbutton)->contrlRect;
- PenSize(3, 3);
- InsetRect(&tmprect, -4, -4);
- if ((*constructbutton)->contrlHilite != 0) {
- PenMode(patBic);
- }
- FrameRoundRect(&tmprect, 16, 16);
- PenNormal();
- SetPort(oldport);
-}
-
-/* Figure out how to subdivide the construction window for the two lists. */
-
-void
-calc_construction_rects()
-{
- int wid, hgt, divide1, divide2;
- Rect tmprect;
-
- /* (should compute based on num chars needed, plus font size) */
- maxtypewid = 250;
- tmprect = constructionwin->portRect;
- runlengthrect = tmprect;
- runlengthrect.left = runlengthrect.right - 100; runlengthrect.top = 5;
- runlengthrect.right -= 20; runlengthrect.bottom = 25;
- wid = tmprect.right - tmprect.left - sbarwid;
- hgt = tmprect.bottom - tmprect.top - sbarwid;
- if (wid / 3 > maxtypewid) {
- divide1 = wid - 2 * maxtypewid;
- divide2 = wid - maxtypewid;
- } else {
- divide1 = wid / 3;
- divide2 = 2 * wid / 3;
- }
- SetRect(&unitlistrect, 0, constructtop, divide1, hgt);
- InsetRect(&unitlistrect, constructmargin, constructmargin);
- SetRect(&typelistrect, divide1, constructtop, divide2, hgt);
- InsetRect(&typelistrect, constructmargin, constructmargin);
- SetRect(&advancelistrect, divide2, constructtop, wid, hgt);
- InsetRect(&advancelistrect, constructmargin, constructmargin);
-}
-
-void
-activate_construction(int activate)
-{
- if (activate)
- TEActivate(run_length_text);
- else
- TEDeactivate(run_length_text);
- LActivate(activate, construction_unit_list);
- LActivate(activate, construction_type_list);
- LActivate(activate, construction_advance_list);
-}
-
-Unit *
-get_selected_construction_unit()
-{
- Point tmpcell;
- Unit *unit;
-
- SetPt(&tmpcell, 0, 0);
- if (LGetSelect(TRUE, &tmpcell, construction_unit_list)) {
- if (tmpcell.v < constructor_units->numunits) {
- unit = unit_in_vector(constructor_units, tmpcell.v);
- if (is_active(unit))
- return unit;
- }
- }
- return NULL;
-}
-
-int
-get_selected_construction_type()
-{
- Point tmpcell;
-
- SetPt(&tmpcell, 0, 0);
- if (LGetSelect(TRUE, &tmpcell, construction_type_list)) {
- if (tmpcell.v < numposstypes) {
- return possibletypes[tmpcell.v];
- }
- }
- return NONUTYPE;
-}
-
-int
-get_selected_construction_advance()
-{
- Point tmpcell;
-
- SetPt(&tmpcell, 0, 0);
- if (LGetSelect(TRUE, &tmpcell, construction_advance_list)) {
- if (tmpcell.v < numpossadvances) {
- return possibleadvances[tmpcell.v];
- }
- }
- return NONATYPE;
-}
-
-void
-scroll_to_selected_construction_unit()
-{
- Unit *unit;
-
- /* Beep and return if there are no maps open currently. */
- if (maplist == NULL) {
- beep();
- return;
- }
- unit = get_selected_construction_unit();
- if (unit != NULL && inside_area(unit->x, unit->y))
- scroll_best_map_to_unit(unit, FALSE);
-}
-
-/* Handle a click anywhere within the construction window. */
-
-void
-do_mouse_down_construction(Point mouse, int mods)
-{
- ControlHandle control;
- short part;
- int a, u;
- Unit *unit;
-
- part = FindControl(mouse, constructionwin, &control);
- if (control == constructbutton) {
- unit = get_selected_construction_unit();
- if (unit != NULL) {
- u = get_selected_construction_type();
- if (u != NONUTYPE) {
- net_push_build_task(unit, u, currunlength, 0, 0);
- update_construction_unit_list(unit);
- return;
- }
- }
- } else if (control == developbutton) {
- unit = get_selected_construction_unit();
- if (unit != NULL) {
- u = get_selected_construction_type();
- if (u != NONUTYPE) {
- net_push_develop_task(unit, u, u_tech_to_build(u));
- update_construction_unit_list(unit);
- return;
- }
- }
- } else if (control == researchbutton) {
- unit = get_selected_construction_unit();
- if (unit != NULL) {
- a = get_selected_construction_advance();
- if (a != NONATYPE) {
- net_set_unit_curadvance(unit->side, unit, a);
- update_construction_unit_list(unit);
- return;
- }
- }
- } else if (PtInRect(mouse, &runlengthrect)) {
- TEClick(mouse, mods, run_length_text);
- /* (should switch this to be current item) */
- } else if (PtInRect(mouse, &unitlistrect)) {
- LClick(mouse, mods, construction_unit_list);
- /* Update the type list to show what could be built and in how long. */
- update_type_list_for_unit(get_selected_construction_unit());
- update_advance_list_for_unit(get_selected_construction_unit());
- } else if (PtInRect(mouse, &typelistrect)) {
- LClick(mouse, mods, construction_type_list);
- /* Update the unit list to show what could build the type */
- update_unit_list_for_type(get_selected_construction_type());
- } else if (PtInRect(mouse, &advancelistrect)) {
- LClick(mouse, mods, construction_advance_list);
- /* Update the unit list to show what could build the type */
- update_unit_list_for_advance(get_selected_construction_advance());
- } else {
- /* Click was not in any useful part of the window. */
- }
-}
-
-int
-do_key_down_construction(key)
-int key;
-{
- int len, runlength, i;
- char buffer[10];
- CharsHandle text;
- Unit *unit;
- short u;
-
- if (isdigit(key)) {
- /* Feed digits to the run length field. */
- TEKey(key, run_length_text);
- text = TEGetText(run_length_text);
- /* Pick out only the initial digits (up to 9). */
- len = min((*run_length_text)->teLength, 9);
- strncpy(buffer, *text, len);
- buffer[len] = '\0';
- runlength = atoi(buffer);
- if (between(1, runlength, 32767)) {
- currunlength = runlength;
- editedrunlength = runlength;
- return TRUE;
- }
- } else if (key == 8) {
- /* Also feed erase key the run length field. */
- TEKey(key, run_length_text);
- return TRUE;
- } else if (key == 13 || key == 3) {
- /* Set construction task and close the window if Enter or Return was hit. */
- unit = get_selected_construction_unit();
- if (unit != NULL) {
- u = get_selected_construction_type();
- if (u != NONUTYPE) {
- net_push_build_task(unit, u, currunlength, 0, 0);
- update_construction_unit_list(unit);
- close_window(constructionwin);
- return TRUE;
- }
- }
- } else {
- for (i = 0; i < numposstypes; ++i) {
- if (key == unitchars[possibletypes[i]]
- /* Skip over types that the selected unit can't build. */
- && est_completion_time(get_selected_construction_unit(), possibletypes[i]) >= 0) {
- select_type_in_construction_window(possibletypes[i]);
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-/* Highlight exactly one specific unit in the construction window, and unhighlight
- any others. */
-
-void
-select_unit_in_construction_window(Unit *unit)
-{
- int i;
- Point tmpcell;
-
- for (i = 0; i < constructor_units->numunits; ++i) {
- SetPt(&tmpcell, 0, i);
- LSetSelect((unit == unit_in_vector(constructor_units, i)), tmpcell, construction_unit_list);
- LAutoScroll(construction_unit_list);
- }
- update_type_list_for_unit(get_selected_construction_unit());
-}
-
-void
-select_type_in_construction_window(int u)
-{
- int i;
- Point tmpcell;
-
- for (i = 0; i < numposstypes; ++i) {
- SetPt(&tmpcell, 0, i);
- LSetSelect((u == possibletypes[i]), tmpcell, construction_type_list);
- LAutoScroll(construction_type_list);
- }
- if (u == NONUTYPE)
- return;
- update_unit_list_for_type(get_selected_construction_type());
-}
-
-void
-select_advance_in_construction_window(int a)
-{
- int i;
- Point tmpcell;
-
- for (i = 0; i < numpossadvances; ++i) {
- SetPt(&tmpcell, 0, i);
- LSetSelect((a == possibleadvances[i]), tmpcell, construction_advance_list);
- LAutoScroll(construction_advance_list);
- }
- if (a == NONATYPE)
- return;
- update_unit_list_for_advance(get_selected_construction_advance());
-}
-
-/* Given a unit (which may be any unit), update the list of constructing units. */
-
-void
-update_construction_unit_list(Unit *unit)
-{
- int i, u;
- Point tmpcell;
-
- if (constructionwin == nil)
- return;
- u = get_selected_construction_type();
- /* We need to look for it even if it might not be ours, since it might
- have been captured or otherwise lost, and needs to be removed. */
- for (i = 0; i < constructor_units->numunits; ++i) {
- if (unit == unit_in_vector(constructor_units, i)) {
- SetPt(&tmpcell, 0, i);
- if (is_active(unit)
- && (can_build_or_help(unit) || can_research(unit))
- && side_controls_unit(dside, unit)) {
- construction_desc(spbuf, unit, u);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_unit_list);
- } else {
- remove_unit_from_vector(constructor_units, unit, i);
- LDelRow(1, tmpcell.v, construction_unit_list);
- }
- return;
- }
- }
- /* Unit was not found, try to add it to the list. */
- maybe_add_unit_to_construction_list(unit);
-}
-
-void
-maybe_add_unit_to_construction_list(Unit *unit)
-{
- Point tmpcell;
-
- if (is_active(unit)
- && (can_build_or_help(unit) || can_research(unit))
- && side_controls_unit(dside, unit)) {
- /* Add this unit to the vector of constructing units. */
- constructor_units = add_unit_to_vector(constructor_units, unit, 0);
- /* (should sort and maybe rearrange list here) */
- /* Add a row at the end of the list. */
- SetPt(&tmpcell, 0, constructor_units->numunits - 1);
- LAddRow(1, constructor_units->numunits - 1, construction_unit_list);
- construction_desc(spbuf, unit, get_selected_construction_type());
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_unit_list);
- }
-}
-
-void
-update_unit_list_for_type(int u)
-{
- int i;
- Point tmpcell;
- Unit *unit;
-
- for (i = 0; i < constructor_units->numunits; ++i) {
- unit = unit_in_vector(constructor_units, i);
- if (unit != NULL) {
- SetPt(&tmpcell, 0, i);
- if (is_active(unit) && unit->side == dside) {
- construction_desc(spbuf, unit, u);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_unit_list);
- } else {
-/* LDelRow(1, tmpcell.v, construction_unit_list); */
- LSetCell("", 0, tmpcell, construction_unit_list);
- }
- }
- }
- adjust_construction_controls();
-}
-
-void
-update_unit_list_for_advance(int a)
-{
- int i;
- Point tmpcell;
- Unit *unit;
-
- for (i = 0; i < constructor_units->numunits; ++i) {
- unit = unit_in_vector(constructor_units, i);
- if (unit != NULL) {
- SetPt(&tmpcell, 0, i);
- if (is_active(unit) && unit->side == dside) {
- research_desc(spbuf, unit, a);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_unit_list);
- } else {
-/* LDelRow(1, tmpcell.v, construction_unit_list); */
- LSetCell("", 0, tmpcell, construction_unit_list);
- }
- }
- }
- adjust_construction_controls();
-}
-
-void
-update_construction_type_list()
-{
- int u;
-
- if (constructionwin == nil)
- return;
- u = get_selected_construction_type();
- update_type_list_for_unit(get_selected_construction_unit());
-}
-
-void
-update_type_list_for_unit(Unit *unit)
-{
- int i;
- Point tmpcell;
-
- for (i = 0; i < numposstypes; ++i) {
- constructible_desc(spbuf, dside, possibletypes[i], get_selected_construction_unit());
- SetPt(&tmpcell, 0, i);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_type_list);
- }
- adjust_construction_controls();
-}
-
-void
-update_construction_advance_list()
-{
- int a;
-
- if (constructionwin == nil)
- return;
- a = get_selected_construction_advance();
- update_advance_list_for_unit(get_selected_construction_unit());
-}
-
-void
-update_advance_list_for_unit(Unit *unit)
-{
- int i;
- Point tmpcell;
-
- for (i = 0; i < numpossadvances; ++i) {
- researchible_desc(spbuf, get_selected_construction_unit(), possibleadvances[i]);
- SetPt(&tmpcell, 0, i);
- LSetCell(spbuf, strlen(spbuf), tmpcell, construction_advance_list);
- }
- adjust_construction_controls();
-}
-
-/* Enable/disable controls according to whether the selected list elements can
- do construction activities. */
-
-void
-adjust_construction_controls()
-{
- int a, u, canconstruct = FALSE, candevelop = FALSE, canresearch = FALSE, len;
- Unit *unit;
-
- unit = get_selected_construction_unit();
- if (unit != NULL) {
- u = get_selected_construction_type();
- if (u != NONUTYPE) {
- if (uu_acp_to_create(unit->type, u) > 0
- && side_can_build(unit->side, u))
- canconstruct = TRUE;
- if (uu_acp_to_develop(unit->type, u) > 0)
- candevelop = TRUE;
- }
- a = get_selected_construction_advance();
- if (a != NONATYPE) {
- if (u_can_research(unit->type)
- && side_can_research(dside, a)) {
- canresearch = TRUE;
- }
- }
- }
- HiliteControl(constructbutton, (canconstruct ? 0 : 255));
- HiliteControl(developbutton, (candevelop ? 0 : 255));
- HiliteControl(researchbutton, (canresearch ? 0 : 255));
- draw_construction_default();
- /* If there is doctrine on construction run length, use it to seed the
- run length in the dialog. */
- if (editedrunlength < 0 && unit != NULL && u != NONUTYPE) {
- len = DEFAULT_RUN;
- if (construction_run_doctrine(unit, u) > 0) {
- len = construction_run_doctrine(unit, u);
- }
- set_construction_run_length(len);
- }
-}
-
-/* Resize the construction window to the given size. */
-
-void
-grow_construction(int h, int v)
-{
- EraseRect(&constructionwin->portRect);
- SizeWindow(constructionwin, h, v, 1);
- adjust_construction_items();
- /* This will force a full redraw at the next update. */
- InvalRect(&constructionwin->portRect);
-}
-
-/* Zooming "rightsizes" the window. */
-
-void
-zoom_construction(int part)
-{
- int titleh, vislinesavail;
- Rect zoomrect;
- GDHandle zoomgd;
-
- EraseRect(&constructionwin->portRect);
- if (part == inZoomOut) {
- if (hasColorQD) {
- zoomgd = best_zoom_screen(&constructionwin->portRect);
- zoomrect = (*zoomgd)->gdRect;
- if (zoomgd == GetMainDevice()) {
- zoomrect.top += GetMBarHeight();
- }
- } else {
- /* If no Color QD, then there is only the one screen. */
- zoomrect = QD(screenBits).bounds;
- zoomrect.top += GetMBarHeight();
- }
- titleh = 20; /* (should calc) */
- zoomrect.top += titleh;
- InsetRect(&zoomrect, 4, 4);
- /* If not many units or types, shrink the zoomed window to fit. */
- vislinesavail = (zoomrect.bottom - zoomrect.top - sbarwid) / 15;
- if (0) {
- zoomrect.bottom = zoomrect.top + 20 * 15 + sbarwid;
- }
- (*((WStateDataHandle) ((WindowPeek) constructionwin)->dataHandle))->stdState = zoomrect;
- }
- ZoomWindow(constructionwin, part, false);
- adjust_construction_items();
- /* This will force a full redraw at the next update. */
- InvalRect(&constructionwin->portRect);
-}
-
-/* Move and resize the list and text objects in the construction window. */
-
-static void
-adjust_construction_items()
-{
- int listwid;
- Point cellsize;
-
- /* Recalculate size and position. */
- calc_construction_rects();
- /* Resize the run length text item. */
- (*run_length_text)->viewRect = runlengthrect;
- (*run_length_text)->destRect = runlengthrect;
- TECalText(run_length_text);
- /* Resize the unit list. */
- listwid = unitlistrect.right - unitlistrect.left - sbarwid;
- LSize(listwid, unitlistrect.bottom - unitlistrect.top,
- construction_unit_list);
- SetPt(&cellsize, max(300, listwid), 12);
- LCellSize(cellsize, construction_unit_list);
- /* Move the type list (is this the approved way to do it?) */
- (*construction_type_list)->rView.left = typelistrect.left;
- listwid = typelistrect.right - typelistrect.left - sbarwid;
- LSize(listwid, typelistrect.bottom - typelistrect.top,
- construction_type_list);
- SetPt(&cellsize, max(300, listwid), 12);
- LCellSize(cellsize, construction_type_list);
- /* Move the advance list (is this the approved way to do it?) */
- (*construction_advance_list)->rView.left = advancelistrect.left;
- listwid = advancelistrect.right - advancelistrect.left - sbarwid;
- LSize(listwid, advancelistrect.bottom - advancelistrect.top,
- construction_advance_list);
- SetPt(&cellsize, max(300, listwid), 12);
- LCellSize(cellsize, construction_advance_list);
-}
-
-/* This is the top-level access to bring up the research window, can be called
- anywhere, anytime. */
-
-void
-show_research_dialog()
-{
- int height, mainheight;
-
- if (!active_display(dside))
- return;
- /* Create it if necessary. */
- if (researchwin == nil) {
- researchwin = GetNewDialog(dSideResearch, NULL, NULL);
- SetWTitle(researchwin, "\pSide Research");
-#if 0
- /* Put it at the bottom adjacent to noticewin. */
- get_main_screen_size(NULL, &mainheight);
- height = researchwin->portRect.bottom - researchwin->portRect.top;
- MoveWindow(researchwin, 411, mainheight - height - 5, false);
- MakeDialogFloat(researchwin);
-#endif
- }
- SelectTheWindow(researchwin);
- ActivateWindow(researchwin, true);
- draw_research_dialog(true);
-}
-
-void
-draw_research_dialog(int force)
-{
- char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE];
- short i, m;
- Str255 pname;
- Handle itemhandle;
- Rect itemrect;
- MenuHandle advanceMenu;
- GrafPtr oldport;
-
- /* Skip if we lack display or research window. */
- if (!active_display(dside) || !researchwin)
- return;
- GetPort(&oldport);
- SetPort(researchwin);
-
- /* Set the autoresearch checkbox. */
- GetDItem(researchwin, diSideResearchCheck, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle, dside->autoresearch);
-
- /* Get the current research topic, if any. */
- if (dside->research_topic == NOADVANCE) {
- strcpy(buf1, "Idle");
- } else if (dside->research_topic == NONATYPE) {
- strcpy(buf1, "Stop Research");
- } else {
- strcpy(buf1, a_type_name(dside->research_topic));
- }
- /* Set the popup menu to the current research topic. */
- advanceMenu = build_research_menu(dside);
- m = CountMItems(advanceMenu);
- GetDItem(researchwin, diSideResearchPopup, NULL, &itemhandle, NULL);
- SetCtlMax((ControlHandle) itemhandle, m); /* Important! */
- for (i = 1; i <= m; i++) {
- GetItem(advanceMenu, i, pname);
- p2c(pname, buf2);
- if (strcmp(buf1, buf2) != 0)
- continue;
- SetCtlValue((ControlHandle) itemhandle, i);
- }
- /* Build the three text fields. */
- if (dside->research_topic == NOADVANCE) {
- strcpy(buf1, "Your wise men are idle.");
- strcpy(buf2, "Pick a new research topic.");
- } else if (dside->research_topic == NONATYPE) {
- strcpy(buf1, "Your wise men are resting.");
- strcpy(buf2, "");
- } else {
- strcpy(buf1, "You are researching :");
- NumToString(dside->advance[dside->research_topic], pname);
- p2c(pname, buf3);
- strcpy(buf2, buf3);
- strcat(buf2, " of ");
- NumToString(a_rp(dside->research_topic), pname);
- p2c(pname, buf3);
- strcat(buf2, buf3);
- strcat(buf2, " points completed.");
- }
- /* Check if either text field needs an update. */
- GetDItem(researchwin, diSideResearchText1, NULL, &itemhandle, NULL);
- GetIText(itemhandle, pname);
- p2c(pname, buf3);
- if (strcmp(buf1, buf3) != 0) {
- c2p(buf1, pname);
- SetIText(itemhandle, pname);
- force = TRUE;
- }
- GetDItem(researchwin, diSideResearchText2, NULL, &itemhandle, NULL);
- GetIText(itemhandle, pname);
- p2c(pname, buf3);
- if (strcmp(buf2, buf3) != 0) {
- c2p(buf2, pname);
- SetIText(itemhandle, pname);
- force = TRUE;
- }
- if (force) {
- DrawDialog(researchwin);
- draw_default_button(researchwin, OkButton);
- }
- SetPort(oldport);
-}
-
-int
-do_key_down_research(char key)
-{
- /* Use the Enter or Return key to exit. */
- if (key == 3 || key == 13) {
- hit_research_dialog(diSideResearchClose);
- return TRUE;
- /* Use the Escape key for the Help button. */
- } else if (key == 27) {
- hit_research_dialog(diSideResearchHelp);
- return TRUE;
- } else return FALSE;
-}
-
-void
-do_mouse_down_research(Point mouse, int mods)
-{
- short ditem;
-
- /* Check if a dialog item was hit and branch to dialog handling code in that case.
- This makes it possible to avoid using the Dialog Manager. */
- ditem = FindDItem(researchwin, mouse) + 1; /* FindDItem returns (ditem -1)! */
- if (ditem > 0) {
- /* First undo previous conversion to locals by do_mouse_down. */
- LocalToGlobal(&mouse);
- hit_research_dialog(ditem);
- return;
- }
-}
-
-
-void
-hit_research_dialog(int ditem)
-{
- short autoresearch, advance, mitem, done = FALSE, a, i, m;
- char sname[32], cname[32];
- MenuHandle advanceMenu;
- HelpNode *helpnode;
- Str255 pname;
- Handle itemhandle;
- GrafPtr oldport;
- Point mouse = {0};
-
- GetPort(&oldport);
- SetPort(researchwin);
-
- switch (ditem) {
-
- /* Toggle autoresearch. */
- case diSideResearchCheck:
- GetDItem(researchwin, ditem, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
- autoresearch = GetCtlValue((ControlHandle) itemhandle);
- net_set_autoresearch(dside, autoresearch);
- /* Turn on research if it was stopped. */
- if (dside->research_topic == NONATYPE)
- net_set_side_research(dside, NOADVANCE);
- done = TRUE;
- break;
-
- /* Pick a new research topic. */
- case diSideResearchPopup:
- advanceMenu = build_research_menu(dside);
- GetDItem(researchwin, ditem, NULL, &itemhandle, NULL);
- /* This is no longer automatically done by the dialog manager. */
- TrackControl((ControlHandle) itemhandle, mouse, (void *) -1);
- /* Make sure the new menu selection is drawn. */
- DrawControls(researchwin);
- mitem = GetCtlValue((ControlHandle) itemhandle);
- GetItem(advanceMenu, mitem, pname);
- p2c(pname, sname);
- /* Stop research if "Stop Research" was selected. */
- if (strcmp(sname, "Stop Research") == NULL) {
- net_set_side_research(dside, NONATYPE);
- } else {
- advance = NOADVANCE;
- for_all_advance_types(a) {
- if (strcmp(a_type_name(a), sname) == NULL) {
- advance = a;
- break;
- }
- }
- net_set_side_research(dside, advance);
- /* Close the window if a real choice was made. */
- if (strcmp(sname, "Idle") != NULL)
- done = TRUE;
- }
- break;
-
- case diSideResearchHelp:
- if (dside->research_topic != NOADVANCE) {
- helpnode = find_help_node(first_help_node, a_type_name(dside->research_topic));
- if (helpnode)
- show_help_window(helpnode);
- else beep();
- }
- break;
-
- case diSideResearchClose:
- done = TRUE;
- break;
-
- default:
- break;
- }
- /* Force a redrawing of the dialog. */
- draw_research_dialog(true);
- if (done)
- close_window(researchwin);
- SetPort(oldport);
-}
-
-/*
- Research dialog for all advanced units belonging to a side. Unit is the city that just made a
- discovery and advance the discovery itself. Set to NULL and (-1) if no discovery was made.
- This is the old global_advance_dialog which was renamed and moved here from macadv.c.
-*/
-
-void
-side_research_dialog(Side *side, Unit *unit, int advance)
-{
- short ditem, mitem, menu, num, text, status, check, done = FALSE, disabled, i, m, s;
- char cname[32], sname[32], buf[BUFSIZE];
- int oldprojects[MAXPROJMENUS + 1];
- int participants[MAXATYPES];
- Str255 pname, pnumber;
- int numprojects = 0;
- int maxprojects;
- int loafers = 0;
- Handle itemhandle;
- MenuHandle doneMenu;
- MenuHandle popMenu;
- GrafPtr oldport;
- Unit *unit2;
- DialogPtr win;
-
- /* Crash bug fix. */
- if (!side)
- return;
- memset(oldprojects, 0, (MAXPROJMENUS + 1) * sizeof(int));
- memset(participants, 0, MAXATYPES * sizeof(int));
-
- /* Always give the own side, designers and debuggers full control. */
- if ((side && side == dside) || Debug || DebugG || DebugM || is_designer(dside)) {
- disabled = FALSE;
- /* Allow peeking at trusted side but with controls disabled. */
- } else if (trusted_side(dside, side)) {
- disabled = TRUE;
- /* Allow peeking at enemy if we can see everything. */
- } else if (dside->see_all) {
- disabled = TRUE;
- } else return;
-
- /* Open the dialog. */
- win = GetNewDialog(dGlobalAdvance, NULL, (DialogPtr) -1);
- GetPort(&oldport);
- SetPort(win);
-
- /* Hide everything except main text. */
- HideDItem(win, diGlobalMadScientist);
- HideDItem(win, diGlobalBusyScientist);
- HideDItem(win, diGlobalIdleScientist);
- for (i = diGlobalIdleMenu; i < diGlobalIdleMenu + 4 * (MAXPROJMENUS + 1); i++)
- HideDItem(win, i);
- for (i = diGlobalIdleCheck; i <= diGlobalIdleCheck + MAXPROJMENUS; i++)
- HideDItem(win, i);
- HideDItem(win, diGlobalMoreNote);
-
- /* Count loafers and project participants. */
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- if (unit2->curadvance != NOADVANCE && unit2->curadvance != advance)
- participants[unit2->curadvance] += 1;
- else loafers += 1;
- }
- /* Count the number of active projects. */
- for_all_advance_types(s) {
- if (participants[s] > 0) {
- numprojects += 1;
- oldprojects[numprojects] = s;
- }
- }
- maxprojects = min(numprojects, MAXPROJMENUS);
-
- /* Load achieved advances into done menu. */
- doneMenu = GetMenu(mAdvanceAchieved);
- for_all_advance_types(s) {
- if (side->advance[s] == DONE) {
- c2p(a_type_name(s), pname);
- AppendMenu(doneMenu, pname);
- }
- }
- /* Load available advances into popup menu. */
- popMenu = GetMenu(mResearchPopup);
- for_all_advance_types(s) {
- if (side_can_research(side, s)) {
- c2p(a_type_name(s), pname);
- AppendMenu(popMenu, pname);
- }
- }
- m = CountMItems(popMenu);
-
- /* Show mad scientist and relevant text if new discovery was signaled. */
- if (advance != NOADVANCE) {
- ShowDItem(win, diGlobalMadScientist);
- if (side == dside)
- strcpy(buf, "Your");
- else strcpy(buf, side_adjective(side));
- strcat(buf, " scientists in ");
- strcat(buf, unit->name);
- strcat(buf, " discover ");
- strcat(buf, a_type_name(advance));
- strcat(buf, "!\r\r");
- strcat(buf, "Pick new advance to research:");
- /* Else show busy scientist and report ongoing research. */
- } else {
- ShowDItem(win, diGlobalBusyScientist);
- if (side == dside)
- strcpy(buf, "Your");
- else strcpy(buf, side_adjective(side));
- strcat(buf, " scientists are busy with the following projects:");
- if (loafers)
- strcat(buf, "\r\rNote : some of them are idle. You should put them to work!");
- }
- /* Show the main text. */
- c2p(buf, pname);
- GetDItem(win, diGlobalMainText, NULL, &itemhandle, NULL);
- SetIText(itemhandle, pname);
-
- /* Maybe show warning about more projects than shown. */
- if (numprojects > MAXPROJMENUS)
- ShowDItem(win, diGlobalMoreNote);
-
- if (loafers) {
- /* Show first menu (idle units) only if needed. */
- GetDItem(win, diGlobalIdleNum, NULL, &itemhandle, NULL);
- NumToString(loafers, pnumber);
- SetIText(itemhandle, pnumber);
- ShowDItem(win, diGlobalIdleNum);
- ShowDItem(win, diGlobalIdleText);
- GetDItem(win, diGlobalIdleMenu, NULL, &itemhandle, NULL);
- ShowDItem(win, diGlobalIdleMenu);
- /* Don't allow other sides to use the menu. */
- if (disabled)
- HiliteControl((ControlHandle) itemhandle, 255);
- /* Also show first checkbox (idle units) if needed. */
- GetDItem(win, diGlobalIdleCheck, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle, TRUE);
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- if (unit2->curadvance != NOADVANCE && unit2->curadvance != advance)
- continue;
- if (unit2->autoresearch != TRUE)
- SetCtlValue((ControlHandle) itemhandle, FALSE);
- }
- ShowDItem(win, diGlobalIdleCheck);
- /* Don't allow other sides to use the checkbox. */
- if (disabled)
- HiliteControl((ControlHandle) itemhandle, 255);
- }
- /* Show project popup menus and associated text items. */
- num = diGlobalIdleNum;
- status = diGlobalIdleStatus;
- check = diGlobalIdleCheck;
- text = diGlobalIdleText;
- menu = diGlobalIdleMenu;
- for (s = 1; s <= maxprojects; s++) {
- /* Show the number of citites on each project. */
- GetDItem(win, ++num, NULL, &itemhandle, NULL);
- NumToString(participants[oldprojects[s]], pnumber);
- SetIText(itemhandle, pnumber);
- ShowDItem(win, num);
- /* Show the "are currently researching" text. */
- ShowDItem(win, ++text);
- /* Show the popup menu with the advance name. */
- GetDItem(win, ++menu, NULL, &itemhandle, NULL);
- SetCtlMax((ControlHandle) itemhandle, m); /* Important! */
- for (i = 1; i <= m; i++) {
- GetItem(popMenu, i, pname);
- p2c(pname, cname);
- if (strcmp(a_type_name(oldprojects[s]), cname) != 0)
- continue;
- SetCtlValue((ControlHandle) itemhandle, i);
- }
- ShowDItem(win, menu);
- /* Don't allow other sides to use the menu. */
- if (disabled)
- HiliteControl((ControlHandle) itemhandle, 255);
- /* Show the status info on the advence. */
- GetDItem(win, ++status, NULL, &itemhandle, NULL);
- NumToString(side->advance[oldprojects[s]], pnumber);
- p2c(pnumber, cname);
- strcat(cname, " / ");
- NumToString(a_rp(oldprojects[s]), pnumber);
- p2c(pnumber, sname);
- strcat(cname, sname);
- c2p(cname, pnumber);
- SetIText(itemhandle, pnumber);
- ShowDItem(win, status);
- /* Show the auto checkbox. */
- GetDItem(win, ++check, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle, TRUE);
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- if (unit2->curadvance != oldprojects[s])
- continue;
- if (unit2->autoresearch != TRUE)
- SetCtlValue((ControlHandle) itemhandle, FALSE);
- }
- ShowDItem(win, check);
- /* Don't allow other sides to use the checkbox. */
- if (disabled)
- HiliteControl((ControlHandle) itemhandle, 255);
- }
-
- /* Finally handle the All units checkbox. */
- GetDItem(win, diGlobalAllCheck, NULL, &itemhandle, NULL);
- /* First assume autoresearch is ON for all units. */
- SetCtlValue((ControlHandle) itemhandle, TRUE);
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- /*Uncheck the box if at least one unit is not on autoresearch. */
- if (unit2->autoresearch != TRUE) {
- SetCtlValue((ControlHandle) itemhandle, FALSE);
- break;
- }
- }
-
- /* Don't allow other sides to use the checkbox. */
- if (disabled)
- HiliteControl((ControlHandle) itemhandle, 255);
-
- ShowWindow(win);
- while (!done) {
- SetCursor(&QD(arrow));
- draw_default_button(win, OkButton);
- ModalDialog(NULL, &ditem);
- switch (ditem) {
- case OkButton:
- /* Don't allow others to change anything. */
- if (disabled) {
- done = TRUE;
- break;
- }
- /* First deal with any idle units. */
- if (loafers) {
- GetDItem(win, diGlobalIdleMenu, NULL, &itemhandle, NULL);
- mitem = GetCtlValue((ControlHandle) itemhandle);
- GetItem(popMenu, mitem, pname);
- p2c(pname, sname);
- /* A new task was chosen for the idle units. */
- if (strcmp("Idle", sname) != 0) {
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- /* Set all Idle units and those who worked on the just acquired advance
- to do selected research instead. */
- if (unit2->curadvance == NOADVANCE || unit2->curadvance == advance)
- unit2->curadvance = atype_from_name(sname);
- }
- } else {
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- /* Set all units who worked on the just acquired advance to Idle. */
- if (unit2->curadvance == advance)
- unit2->curadvance = NOADVANCE;
- }
- }
- /* Then deal with the first auto checkbox. */
- GetDItem(win, diGlobalIdleCheck, NULL, &itemhandle, NULL);
- check = GetCtlValue((ControlHandle) itemhandle);
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- if (strcmp("Idle", sname) == 0) {
- if (unit2->curadvance == NOADVANCE || unit2->curadvance == advance) {
- unit2->autoresearch = check;
- } else continue;
- } else {
- if (unit2->curadvance == atype_from_name(sname)) {
- unit2->autoresearch = check;
- } else continue;
- }
- }
- }
- /* Then deal with ongoing research projects. */
- for (i = 1; i <= maxprojects; i++) {
- GetDItem(win, diGlobalIdleMenu + i, NULL, &itemhandle, NULL);
- mitem = GetCtlValue((ControlHandle) itemhandle);
- GetItem(popMenu, mitem, pname);
- p2c(pname, sname);
- /* Only proceed if we changed the project. */
- if (strcmp(a_type_name(oldprojects[i]), sname) != 0) {
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- /* Change units involved in the old project to new goal. */
- if (unit2->curadvance == oldprojects[i]) {
- if (strcmp("Idle", sname) == 0)
- unit2->curadvance = NOADVANCE;
- else unit2->curadvance = atype_from_name(sname);
- }
- }
- }
- /* Finally deal with auto checkboxes. */
- GetDItem(win, diGlobalIdleCheck + i, NULL, &itemhandle, NULL);
- check = GetCtlValue((ControlHandle) itemhandle);
- for_all_side_units(side, unit2) {
- if (!u_can_research(unit2->type))
- continue;
- if (unit2->curadvance != oldprojects[i])
- continue;
- unit2->autoresearch = check;
- }
- }
- done = TRUE;
- break;
-
- case CancelButton:
- done = TRUE;
- break;
-
- default:
- /* Handle auto checkboxes. */
- for (i = 0; i <= maxprojects; i++) {
- if (ditem == diGlobalIdleCheck + i) {
- GetDItem(win, ditem, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle,
- !GetCtlValue((ControlHandle) itemhandle));
- }
- }
- /* Handle All units checkbox. Toggle all other checkboxes. */
- if (ditem == diGlobalAllCheck) {
- GetDItem(win, ditem, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle,
- !GetCtlValue((ControlHandle) itemhandle));
- check = GetCtlValue((ControlHandle) itemhandle);
- for (i = 0; i <= maxprojects; i++) {
- GetDItem(win, diGlobalIdleCheck + i, NULL, &itemhandle, NULL);
- SetCtlValue((ControlHandle) itemhandle, check);
- }
- }
- break;
- }
- }
- /* Close the dialog. */
- DisposeDialog(win);
- /* Restore old port. */
- SetPort(oldport);
-}
-
-/* History window. */
-
-/* This is the top-level access to bring up the history window, can be called
- anywhere, anytime. */
-
-void
-show_history_window()
-{
- if (historywin == nil) {
- create_history_window();
- }
- SelectTheWindow(historywin);
- ActivateWindow(historywin, true);
-}
-
-void
-create_history_window()
-{
- Rect vscrollrect;
-
- /* Create the window, color if possible, since images may be in color. */
- if (hasColorQD) {
- historywin = GetNewCWindow(wHistory, NULL, NULL);
- } else {
- historywin = GetNewWindow(wHistory, NULL, NULL);
- }
- SetWTitle(historywin, "\pHistory");
- SizeWindow(historywin, 400, 122, true);
- SetPort(historywin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- /* (should calc max based on size of font and height of screen) */
- histcontents = (HistEvent **) xmalloc(maxvishistlines * sizeof(HistEvent *));
- vscrollrect = historywin->portRect;
- vscrollrect.top -= 1;
- vscrollrect.bottom -= floatsbarwid - 1;
- vscrollrect.left = vscrollrect.right - floatsbarwid;
- vscrollrect.right += 1;
- histvscrollbar = NewControl(historywin, &vscrollrect, "\p", TRUE,
- 0, 0, 100, scrollBarProc, 0L);
- HiliteControl(histvscrollbar, 0);
- total_history_lines = update_total_hist_lines(dside);
- set_history_scrollbar();
- /* Finally make it floating. */
- MakeFloat(historywin);
-}
-
-static void
-calc_history_layout()
-{
- total_history_lines = update_total_hist_lines(dside);
- set_history_scrollbar();
- numhistcontents = build_hist_contents(dside, GetCtlValue(histvscrollbar), histcontents,
- numvishistlines);
-}
-
-static void
-set_history_scrollbar()
-{
- int hgt, oldval, oldmax;
- HistEvent *nexthevt;
-
- /* Compute the number of lines available for displaying history. */
- hgt = historywin->portRect.bottom - historywin->portRect.top;
- history_line_spacing = small_line_spacing;
- numvishistlines = hgt / history_line_spacing;
- /* Tweak the scrollbar appropriately. */
- oldval = GetCtlValue(histvscrollbar);
- oldmax = GetCtlMax(histvscrollbar);
- SetCtlMax(histvscrollbar, max(0, total_history_lines - numvishistlines + 1));
- HiliteControl(histvscrollbar, (GetCtlMax(histvscrollbar) > 0 ? 0 : 255));
- SetCtlValue(histvscrollbar, GetCtlMax(histvscrollbar));
-}
-
-void
-draw_history()
-{
- int i, n, headdate, numchars;
- char *datestr, hdatebuf[100];
- Rect contentrect;
- HistEvent *hevt;
-
- if (!active_display(dside) || historywin == nil)
- return;
- contentrect = historywin->portRect;
- contentrect.right -= floatsbarwid;
- EraseRect(&contentrect);
- /* Trick build_hist_contents into getting one extra histevent which we
- may need to pad out the window. */
- ++numvishistlines;
- numhistcontents = build_hist_contents(dside, GetCtlValue(histvscrollbar),
- histcontents, numvishistlines);
- --numvishistlines;
- /* Dont draw "Turn X" twice. */
- if (histcontents[0] != NULL) {
- /* Draw the header line. */
- MoveTo(4, small_line_spacing -2);
- headdate = (histcontents[0] ? histcontents[0] : histcontents[1])->startdate;
- /* (should be relative) */
- datestr = absolute_date_string(headdate);
- sprintf(hdatebuf, "%s ...", datestr);
- /* (should clip to drawing only visible chars) */
- numchars = strlen(hdatebuf);
- TextFace(bold);
- ForeColor(redColor);
- DrawText(hdatebuf, 0, numchars);
- TextFace(normal);
- ForeColor(blackColor);
- --numhistcontents;
- }
- /* Now draw each event or date. */
- for (i = 0; i <= numhistcontents; ++i) {
- if (histcontents[i] != NULL) {
- draw_historical(histcontents[i], i, TRUE);
- } else {
- draw_historical(histcontents[i+1], i, FALSE);
- }
- }
-}
-
-void
-draw_historical(HistEvent *hevt, int y, int drawevt)
-{
- int pos, numchars;
- char *datestr, buf[500];
-
- if (hevt == NULL)
- return;
- TextFont(small_font_id);
- TextSize(small_font_size);
- pos = history_line_spacing * y + small_line_spacing - 2;
- /* Make room for "Turn X ..." header. */
- if (histcontents[0] != NULL)
- pos += small_line_spacing;
- MoveTo((drawevt ? 16 : 4), pos);
- if (drawevt) {
- historical_event_desc(dside, hevt, buf);
- /* Make the first letter a capital ... */
- buf[0] = uppercase(buf[0]);
- /* ... and add a period at the end. */
- sprintf(buf, "%s.", buf);
- numchars = strlen(buf);
- DrawText(buf, 0, numchars);
- } else {
- datestr = absolute_date_string(hevt->startdate);
- sprintf(buf, "%s:", datestr);
- numchars = strlen(buf);
- TextFace(bold);
- ForeColor(redColor);
- DrawText(buf, 0, numchars);
- TextFace(normal);
- ForeColor(blackColor);
- }
-}
-
-void
-update_history_window(HistEvent *hevt)
-{
- HistEvent *prevfirst, *prevsecond;
-
- prevfirst = histcontents[0];
- prevsecond = histcontents[1];
- SetPort(historywin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- calc_history_layout();
- if (histcontents[0] != prevfirst
- || histcontents[1] != prevsecond
- || numvishistlines > total_history_lines) {
- force_update(historywin);
- }
-}
-
-static pascal void
-history_scroll_fn(ControlHandle control, short code)
-{
- int curvalue, minvalue, maxvalue, pagesize, jump;
-
- curvalue = GetCtlValue(control);
- minvalue = GetCtlMin(control);
- maxvalue = GetCtlMax(control);
- pagesize = numvishistlines;
- if (pagesize > 1)
- pagesize -= 1;
- switch (code) {
- case inPageDown:
- jump = pagesize;
- break;
- case inDownButton:
- jump = 1;
- break;
- case inPageUp:
- jump = - pagesize;
- break;
- case inUpButton:
- jump = -1;
- break;
- default:
- jump = 0;
- break;
- }
- curvalue = max(min(curvalue + jump, maxvalue), minvalue);
- SetCtlValue(control, curvalue);
-}
-
-void
-do_mouse_down_history(Point mouse, int mods)
-{
- ControlHandle control;
- short oldval, part, value;
-
- if (history_scroll_proc == NULL)
- history_scroll_proc = NewControlActionProc(history_scroll_fn);
-
- oldval = GetCtlValue(histvscrollbar);
-
- part = FindControl(mouse, historywin, &control);
- if (control == histvscrollbar) {
- switch (part) {
- case inThumb:
- part = TrackControl(control, mouse, NULL);
- break;
- default:
- part = TrackControl(control, mouse, history_scroll_proc);
- break;
- }
- value = GetCtlValue(control);
- if (value != oldval) {
- Dprintf("New scroll is %d, old was %d\n", value, oldval);
- numhistcontents = build_hist_contents(dside, value, histcontents, numvishistlines);
- force_update(historywin);
- }
- } else {
- /* anything to do here? */
- }
-}
-
-/* Grow/shrink the history window to the given size. */
-
-void
-grow_history(int h, int v)
-{
- EraseRect(&historywin->portRect);
- SizeWindow(historywin, h, v, 1);
- move_history_scrollbar(h, v);
- /* This will force a full redraw at the next update. */
- InvalRect(&historywin->portRect);
-}
-
-/* Zoom the history window to its best maximal size. */
-
-void
-zoom_history(int part)
-{
- int titleh, vislinesavail;
- Rect zoomrect;
- GDHandle zoomgd;
-
- EraseRect(&historywin->portRect);
- if (part == inZoomOut) {
- if (hasColorQD) {
- zoomgd = best_zoom_screen(&historywin->portRect);
- zoomrect = (*zoomgd)->gdRect;
- if (zoomgd == GetMainDevice()) {
- zoomrect.top += GetMBarHeight();
- }
- } else {
- /* If no Color QD, then there is only one screen. */
- zoomrect = QD(screenBits).bounds;
- zoomrect.top += GetMBarHeight();
- }
- titleh = 20; /* (should calc) */
- zoomrect.top += titleh;
- InsetRect(&zoomrect, 4, 4);
- /* If not much history, shrink the zoomed window to fit. */
- vislinesavail = (zoomrect.bottom - zoomrect.top - sbarwid) / history_line_spacing;
- total_history_lines = update_total_hist_lines(dside);
- if (vislinesavail > total_history_lines) {
- zoomrect.bottom = zoomrect.top + total_history_lines * history_line_spacing + sbarwid;
- }
- (*((WStateDataHandle) ((WindowPeek) historywin)->dataHandle))->stdState = zoomrect;
- }
- ZoomWindow(historywin, part, false);
- move_history_scrollbar(window_width(historywin), window_height(historywin));
- /* This will force a full redraw at the next update. */
- InvalRect(&historywin->portRect);
-}
-
-void
-move_history_scrollbar(int h, int v)
-{
- MoveControl(histvscrollbar, h - floatsbarwid, -1);
- SizeControl(histvscrollbar, floatsbarwid + 1, v + 1 - floatsbarwid + 1);
- set_history_scrollbar();
-}
-
-/* notice window. */
-
-/* This is the top-level access to bring up the notice window, can be called
- anywhere, anytime. */
-
-void
-show_notice_window()
-{
- if (noticewin == nil) {
- create_notice_window();
- }
- SelectTheWindow(noticewin);
- ActivateWindow(noticewin, true);
-}
-
-void
-create_notice_window()
-{
- int h, v, mainheight;
- Rect destrect, viewrect, vscrollrect, tmprect;
-
- /* Create the window, color if possible, since images may be in color. */
- if (hasColorQD) {
- noticewin = GetNewCWindow(wFloatResize, NULL, NULL);
- } else {
- noticewin = GetNewWindow(wFloatResize, NULL, NULL);
- }
- SetWTitle(noticewin, "\pNotices");
- SizeWindow(noticewin, 400, 122, true);
- SetPort(noticewin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- h = window_width(noticewin); v = window_height(noticewin);
- SetRect(&viewrect, 5, 0, h - floatsbarwid, v);
- destrect = viewrect;
- /* Use TEStyleNew instead of TENew to enable text styles. */
- notice_text = TEStyleNew(&destrect, &destrect);
- /* Set up a vertical scrollbar. */
- vscrollrect = noticewin->portRect;
- vscrollrect.top -= 1;
- vscrollrect.bottom -= floatsbarwid - 1;
- vscrollrect.left = vscrollrect.right - floatsbarwid;
- vscrollrect.right += 1;
- notice_v_scrollbar =
- NewControl(noticewin, &vscrollrect, "\p", TRUE, 0, 0, 0, scrollBarProc, 0L);
- HiliteControl(notice_v_scrollbar, 0);
- if (1 /* position notices at bottom of main screen */) {
- get_main_screen_size(NULL, &mainheight);
- tmprect = noticewin->portRect;
- MoveWindow(noticewin,
- 3,
- mainheight - (tmprect.bottom - tmprect.top) - 5,
- FALSE);
- }
- /* Finally make it floating. */
- MakeFloat(noticewin);
-}
-
-void
-append_notice(char *str)
-{
- /* Delete old notices. */
- if (((*notice_text)->teLength) > 30000) {
- TESetSelect(0, (*notice_text)->teLength - 30000, notice_text);
- TEDelete(notice_text);
- }
-#if defined(THINK_C) || defined(__MWERKS__)
- /* Hack up newlines so that TextEdit recognizes them. */
- {
- int i;
-
- for (i = 0; i < strlen(str); ++i) {
- if (str[i] == '\n')
- str[i] = '\r';
- }
- }
-#endif
- /* TEStyleNew sets lineHeight to -1 to enable variable heights. However,
- since adjust_notice_scrollbar uses lineHeight we must set it manually to
- a suitable fixed value. */
- (*notice_text)->lineHeight = small_font_size + 3;
- /* Also update size and font from defaults. */
- noticeStyle->tsSize = small_font_size;
- noticeStyle->tsFont = small_font_id;
- /* New turn notices end with a colon. Use blue bold face text. */
- if (str[strlen(str) - 1] == ':') {
- noticeStyle->tsColor = (RGBColor) {0, 0, 0xFFFF};
- noticeStyle->tsFace = 1;
- } else {
- noticeStyle->tsColor = (RGBColor) {0, 0, 0};
- noticeStyle->tsFace = 0;
- }
- /* Set insertion point and style. */
- TESetSelect(32767, 32767, notice_text);
- TESetStyle(doFace + doFont + doSize + doColor, noticeStyle, false, notice_text);
- /* Add a linefeed before a new turn notice. */
- if (str[strlen(str) - 1] == ':') {
-// TEStyleInsert("\r", strlen("\r"), 0, notice_text);
- /* Indent all other notices by two tabs. */
- } else {
- TEStyleInsert("\t\t", strlen("\t\t"), 0, notice_text);
- }
- /* Insert the notice itself. */
- TEStyleInsert(str, strlen(str), 0, notice_text);
- /* Add a linefeed at the end of each notice. */
- TEStyleInsert("\r", strlen("\r"), 0, notice_text);
- /* Draw it. */
- draw_notice();
-}
-
-void
-draw_notice()
-{
- GrafPtr oldport;
-
- GetPort(&oldport);
- SetPort(noticewin);
- adjust_notice_scrollbar();
- TEUpdate(&(noticewin->portRect), notice_text);
- SetPort(oldport);
-}
-
-void
-adjust_notice_scrollbar()
-{
- int oldmax, newmax, oldvalue, newvalue;
-
- oldvalue = GetCtlValue(notice_v_scrollbar);
- oldmax = GetCtlMax(notice_v_scrollbar);
-
- /* Compute and set the new scrollbar max value. */
- newmax = (*notice_text)->nLines
- - (((*notice_text)->viewRect.bottom
- - (*notice_text)->viewRect.top)
- / (*notice_text)->lineHeight);
- if (newmax < 0)
- newmax = 0;
- SetCtlMax(notice_v_scrollbar, newmax);
-
- /* If the thumb was at max, move it to the new max. */
- if (oldvalue == oldmax) {
- newvalue = newmax;
- /* Else leave it alone. */
- } else {
- newvalue = oldvalue;
- }
- SetCtlValue(notice_v_scrollbar, newvalue);
-
- /* Finally do the text scrolling. */
- TEScroll(0, (*notice_text)->viewRect.top
- - (*notice_text)->destRect.top
- - (*notice_text)->lineHeight * newvalue,
- notice_text);
-}
-
-void
-activate_notice(int activate)
-{
- HiliteControl(notice_v_scrollbar, (activate ? 0 : 255));
- if (activate)
- TEActivate(notice_text);
- else
- TEDeactivate(notice_text);
-}
-
-static pascal void
-notice_vscroll_fn(ControlHandle control, short code)
-{
- int oldvalue, curvalue, minvalue, maxvalue, pagesize, jump;
-
- curvalue = GetCtlValue(control);
- minvalue = GetCtlMin(control);
- maxvalue = GetCtlMax(control);
- pagesize = ((*notice_text)->viewRect.bottom - (*notice_text)->viewRect.top) /
- (*notice_text)->lineHeight;
- if (pagesize > 1)
- pagesize -= 1;
- switch (code) {
- case inPageDown:
- jump = pagesize;
- break;
- case inDownButton:
- jump = 1;
- break;
- case inPageUp:
- jump = - pagesize;
- break;
- case inUpButton:
- jump = -1;
- break;
- default:
- jump = 0;
- break;
- }
- oldvalue = curvalue;
- curvalue = max(min(curvalue + jump, maxvalue), minvalue);
- SetCtlValue(control, curvalue);
- /* Calculate the actual jump and use it to adjust the text. */
- jump = curvalue - oldvalue;
- if (jump != 0)
- TEScroll(0, - jump * (*notice_text)->lineHeight, notice_text);
-}
-
-/* Respond to an event occurring in the notice window. */
-
-void
-do_mouse_down_notice(Point mouse, int mods)
-{
- ControlHandle control;
- short part, value;
-
- if (notice_vscroll_proc == NULL)
- notice_vscroll_proc = NewControlActionProc(notice_vscroll_fn);
-
- part = FindControl(mouse, noticewin, &control);
- if (control == notice_v_scrollbar) {
- if (part != 0) {
- switch (part) {
- case inPageDown:
- case inDownButton:
- case inPageUp:
- case inUpButton:
- value = TrackControl(control, mouse, notice_vscroll_proc);
- break;
- case inThumb:
- value = GetCtlValue(control);
- if ((part = TrackControl(control, mouse, nil)) != 0) {
- value -= GetCtlValue(control);
- if (value != 0) {
- TEScroll(0, value * (*notice_text)->lineHeight, notice_text);
- }
- }
- break;
- }
- }
- } else if (PtInRect(mouse, &((*notice_text)->viewRect))) {
- TEClick(mouse, 0, notice_text);
- }
-}
-
-void
-grow_notice(int h, int v)
-{
- EraseRect(¬icewin->portRect);
- SizeWindow(noticewin, h, v, 1);
- MoveControl(notice_v_scrollbar, h - floatsbarwid, -1);
- SizeControl(notice_v_scrollbar, floatsbarwid + 1, v + 1 - floatsbarwid + 1);
- (*notice_text)->viewRect.right = h - floatsbarwid;
- (*notice_text)->viewRect.bottom = v;
- (*notice_text)->destRect.right = h - floatsbarwid;
- TECalText(notice_text);
- InvalRect(¬icewin->portRect);
-}
-
-void
-zoom_notice(int part)
-{
- int titleh, h, v;
- Rect zoomrect;
- GDHandle gd, zoomgd;
-
- EraseRect(¬icewin->portRect);
- if (part == inZoomOut) {
- if (hasColorQD) {
- zoomgd = best_zoom_screen(¬icewin->portRect);
- zoomrect = (*zoomgd)->gdRect;
- if (zoomgd == GetMainDevice()) {
- zoomrect.top += GetMBarHeight();
- }
- InsetRect(&zoomrect, 3, 3);
- } else {
- /* If no Color QD, then there is only the one screen. */
- zoomrect = QD(screenBits).bounds;
- zoomrect.top += GetMBarHeight();
- InsetRect(&zoomrect, 4, 4);
- }
- titleh = 20; /* (should calc) */
- zoomrect.top += titleh;
- (*((WStateDataHandle) ((WindowPeek) noticewin)->dataHandle))->stdState = zoomrect;
- }
- ZoomWindow(noticewin, part, false);
- h = window_width(noticewin); v = window_height(noticewin);
- MoveControl(notice_v_scrollbar, h - floatsbarwid, -1);
- SizeControl(notice_v_scrollbar, floatsbarwid + 1, v + 1 - floatsbarwid + 1);
- adjust_notice_scrollbar();
- (*notice_text)->viewRect.right = h - floatsbarwid;
- (*notice_text)->viewRect.bottom = v;
- (*notice_text)->destRect.right = h - floatsbarwid;
- TECalText(notice_text);
- /* This will force a full redraw at the next update. */
- InvalRect(¬icewin->portRect);
-}
-
-/* scores window. */
-
-/* This is the top-level access to bring up the scores window, can be called
- anywhere, anytime. */
-
-void
-show_scores_window()
-{
- if (scoreswin == nil) {
- create_scores_window();
- append_scores(get_scores(dside));
- }
- SelectTheWindow(scoreswin);
- ActivateWindow(scoreswin, true);
-}
-
-void
-create_scores_window()
-{
- int h, v;
- Rect destrect, viewrect, vscrollrect;
-
- /* Create the window, color if possible, since images may be in color. */
- if (hasColorQD) {
- scoreswin = GetNewCWindow(wScores, NULL, NULL);
- } else {
- scoreswin = GetNewWindow(wScores, NULL, NULL);
- }
- SetPort(scoreswin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- h = window_width(scoreswin); v = window_height(scoreswin);
- SetRect(&viewrect, 5, 0, h - floatsbarwid, v);
- destrect = viewrect;
- scores_text = TENew(&destrect, &destrect);
- /* Set up a vertical scrollbar. */
- vscrollrect = scoreswin->portRect;
- vscrollrect.top -= 1;
- vscrollrect.bottom -= floatsbarwid - 1;
- vscrollrect.left = vscrollrect.right - floatsbarwid;
- vscrollrect.right += 1;
- scores_v_scrollbar =
- NewControl(scoreswin, &vscrollrect, "\p", TRUE, 0, 0, 0, scrollBarProc, 0L);
- HiliteControl(scores_v_scrollbar, 0);
- add_window_menu_item("Scores", scoreswin);
- /* Finally make it floating. */
- MakeFloat(scoreswin);
-}
-
-void
-append_scores(char *str)
-{
- /* Delete old scoress. */
- if (((*scores_text)->teLength) > 30000) {
- TESetSelect(0, (*scores_text)->teLength - 30000, scores_text);
- TEDelete(scores_text);
- }
-#if defined(THINK_C) || defined(__MWERKS__)
- /* Hack up newlines so that TextEdit recognizes them. */
- {
- int i;
-
- for (i = 0; i < strlen(str); ++i) {
- if (str[i] == '\n')
- str[i] = '\r';
- }
- }
-#endif
- TESetSelect(32767, 32767, scores_text);
- TEInsert(str, strlen(str), scores_text);
- TEInsert("\r", strlen("\r"), scores_text);
- TESetSelect(32767, 32767, scores_text);
- (*scores_text)->destRect = (*scores_text)->viewRect;
- /* Update on the screen. */
- adjust_scores_scrollbar();
- draw_scores();
-}
-
-void
-draw_scores()
-{
- Rect tmprect;
- GrafPtr oldport;
-
- GetPort(&oldport);
- SetPort(scoreswin);
- TextFont(small_font_id);
- TextSize(small_font_size);
- SetRect(&tmprect, 5, 40, 5 + 32, 40 + 32);
- EraseRect(&tmprect);
- TEUpdate(&(scoreswin->portRect), scores_text);
- SetPort(oldport);
- adjust_scores_scrollbar();
-}
-
-void
-adjust_scores_scrollbar()
-{
- int lines, oldmax, newmax, oldvalue, newvalue;
-
- oldvalue = GetCtlValue(scores_v_scrollbar);
- oldmax = GetCtlMax(scores_v_scrollbar);
- lines = (*scores_text)->nLines;
- /* Account for a return at the end of the text. */
- if (*(*(*scores_text)->hText + (*scores_text)->teLength - 1) == 0x0d)
- ++lines;
- newmax = lines - (((*scores_text)->viewRect.bottom - (*scores_text)->viewRect.top)
- / (*scores_text)->lineHeight);
- if (newmax < 0)
- newmax = 0;
- SetCtlMax(scores_v_scrollbar, newmax);
- if (oldvalue == oldmax) {
- /* If the thumb was at max, move it to the new max. */
- newvalue = newmax;
- } else {
- /* Otherwise adjust it proportionally. */
- newvalue = ((*scores_text)->viewRect.top - (*scores_text)->destRect.top)
- / (*scores_text)->lineHeight;
- if (newvalue < 0)
- newvalue = 0;
- if (newvalue > newmax)
- newvalue = newmax;
- }
- SetCtlValue(scores_v_scrollbar, newvalue);
- TEScroll(0, ((*scores_text)->viewRect.top - (*scores_text)->destRect.top)
- - (GetCtlValue(scores_v_scrollbar) * (*scores_text)->lineHeight),
- scores_text);
-}
-
-void
-activate_scores(int activate)
-{
- HiliteControl(scores_v_scrollbar, (activate ? 0 : 255));
- if (activate)
- TEActivate(scores_text);
- else
- TEDeactivate(scores_text);
-}
-
-static pascal void
-scores_vscroll_fn(ControlHandle control, short code)
-{
- int oldvalue, curvalue, minvalue, maxvalue, pagesize, jump;
-
- curvalue = GetCtlValue(control);
- minvalue = GetCtlMin(control);
- maxvalue = GetCtlMax(control);
- pagesize = ((*scores_text)->viewRect.bottom - (*scores_text)->viewRect.top) /
- (*scores_text)->lineHeight;
- if (pagesize > 1)
- pagesize -= 1;
- switch (code) {
- case inPageDown:
- jump = pagesize;
- break;
- case inDownButton:
- jump = 1;
- break;
- case inPageUp:
- jump = - pagesize;
- break;
- case inUpButton:
- jump = -1;
- break;
- default:
- jump = 0;
- break;
- }
- oldvalue = curvalue;
- curvalue = max(min(curvalue + jump, maxvalue), minvalue);
- SetCtlValue(control, curvalue);
- /* Calculate the actual jump and use it to adjust the text. */
- jump = curvalue - oldvalue;
- if (jump != 0)
- TEScroll(0, - jump * (*scores_text)->lineHeight, scores_text);
-}
-
-/* Respond to an event occurring in the scores window. */
-
-void
-do_mouse_down_scores(Point mouse, int mods)
-{
- ControlHandle control;
- short part, value;
-
- if (scores_vscroll_proc == NULL)
- scores_vscroll_proc = NewControlActionProc(scores_vscroll_fn);
-
- part = FindControl(mouse, scoreswin, &control);
- if (control == scores_v_scrollbar) {
- if (part != 0) {
- switch (part) {
- case inPageDown:
- case inDownButton:
- case inPageUp:
- case inUpButton:
- value = TrackControl(control, mouse, scores_vscroll_proc);
- break;
- case inThumb:
- value = GetCtlValue(control);
- if ((part = TrackControl(control, mouse, nil)) != 0) {
- value -= GetCtlValue(control);
- if (value != 0) {
- TEScroll(0, value * (*scores_text)->lineHeight, scores_text);
- }
- }
- break;
- }
- }
- } else if (PtInRect(mouse, &((*scores_text)->viewRect))) {
- TEClick(mouse, 0, scores_text);
- }
-}
-
-void
-grow_scores(int h, int v)
-{
- EraseRect(&scoreswin->portRect);
- SizeWindow(scoreswin, h, v, 1);
- MoveControl(scores_v_scrollbar, h - floatsbarwid, -1);
- SizeControl(scores_v_scrollbar, floatsbarwid + 1, v + 1 - floatsbarwid + 1);
- (*scores_text)->viewRect.right = h - floatsbarwid;
- (*scores_text)->viewRect.bottom = v;
- (*scores_text)->destRect.right = h - floatsbarwid;
- TECalText(scores_text);
- InvalRect(&scoreswin->portRect);
-}
-
-void
-zoom_scores(int part)
-{
- int titleh, h, v;
- Rect zoomrect;
- GDHandle gd, zoomgd;
-
- EraseRect(&scoreswin->portRect);
- if (part == inZoomOut) {
- if (hasColorQD) {
- zoomgd = best_zoom_screen(&scoreswin->portRect);
- zoomrect = (*zoomgd)->gdRect;
- if (zoomgd == GetMainDevice()) {
- zoomrect.top += GetMBarHeight();
- }
- InsetRect(&zoomrect, 3, 3);
- } else {
- /* If no Color QD, then there is only the one screen. */
- zoomrect = QD(screenBits).bounds;
- zoomrect.top += GetMBarHeight();
- InsetRect(&zoomrect, 4, 4);
- }
- titleh = 20; /* (should calc) */
- zoomrect.top += titleh;
- (*((WStateDataHandle) ((WindowPeek) scoreswin)->dataHandle))->stdState = zoomrect;
- }
- ZoomWindow(scoreswin, part, false);
- h = window_width(scoreswin); v = window_height(scoreswin);
- MoveControl(scores_v_scrollbar, h - floatsbarwid, -1);
- SizeControl(scores_v_scrollbar, floatsbarwid + 1, v + 1 - floatsbarwid + 1);
- adjust_scores_scrollbar();
- (*scores_text)->viewRect.right = h - floatsbarwid;
- (*scores_text)->viewRect.bottom = v;
- (*scores_text)->destRect.right = h - floatsbarwid;
- TECalText(scores_text);
- /* This will force a full redraw at the next update. */
- InvalRect(&scoreswin->portRect);
-}