|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 9111 (0x2397) Types: TextFile Names: »curses.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Xconq/curses.c«
/* Copyright (c) 1987, 1988 Stanley T. Shebs, University of Utah. */ /* This program may be used, copied, modified, and redistributed freely */ /* for noncommercial purposes, so long as this notice remains intact. */ /* RCS $Header: curses.c,v 1.1 88/06/21 12:30:04 shebs Exp $ */ /* Interface implementations for the curses version of xconq. */ /* This file is rather simple, since there is no support for multiple */ /* displays, no flashy graphics, and very little optimization. */ #include "config.h" #include "misc.h" #include "period.h" #include "side.h" #include "map.h" #undef bool /* ugh */ #include <curses.h> #ifdef UNIX #include <signal.h> /* needed for ^C handling */ #endif UNIX #define INFOLINES 4 int helpwinlines = 1; /* Positions and sizes of the windows. */ int wx[20], wy[20], ww[20], wh[20]; int nextwin = 0; /* number of next window to open */ bool alreadyopen = FALSE; /* flag to prevent double opening */ /* Put in a default player, probably the invoker of the program. */ /* Nonempty host name not actually used, but needed to keep things */ /* straight. */ add_default_player() { add_player(TRUE, "curses"); } /* Decide what to do about ^C interrupts. */ #ifdef UNIX stop_handler() { if (numhumans == 0 || Debug) { close_displays(); exit(1); } } #endif UNIX init_sighandlers() { #ifdef UNIX signal(SIGINT, stop_handler); #endif UNIX } /* "Opening" a curses "display" just involves a standard sequence of calls. */ /* Unfortunately, the "standard sequence" varies from system to system... */ open_display(side) Side *side; { if (!alreadyopen) { initscr(); nonl(); noecho(); #ifdef HPUX cbreak(); #endif HPUX #ifdef BSD crmode(); #endif BSD clear(); side->display = 1L; alreadyopen = TRUE; return TRUE; } else { /* if we got here, we're in big trouble, so clean up quickly */ clear(); refresh(); endwin(); printf("Can't open a second display!\n"); return FALSE; } } /* A predicate that tests whether our display can safely be written to. */ /* This is permitted to do side-effects, although curses doesn't need */ /* anything special. */ active_display(side) Side *side; { return (side != NULL && side->host && !side->lost && side->display); } /* Display will use every character position we can get our hands on. */ display_width(side) Side *side; { return COLS; } display_height(side) Side *side; { return LINES; } /* Displaying the world map usually requires a large bitmap display. */ world_display(side) Side *side; { return FALSE; } /* Most sizes of things are 1 (i.e. one character cell). */ init_misc(side) Side *side; { side->fw = side->fh = side->hh = side->hch = side->uw = side->uh = 1; side->hw = 2; side->bd = side->margin = 0; } /* The "root window" covers our entire display. In theory, the size of the */ /* screen could exceed what xconq needs, but this is wildly improbable. */ create_main_window(side) Side *side; { create_window(side, 0, 0, COLS, LINES); } /* Subwindow creator. */ create_window(side, x, y, w, h) Side *side; int x, y, w, h; { if (x + w > COLS) w = COLS - x; if (y + h > LINES) h = LINES - y; wx[nextwin] = x; wy[nextwin] = y; ww[nextwin] = w; wh[nextwin] = h; return (nextwin++); } /* Help window has to be larger than most terminals allow, so blow it off. */ create_help_window(side) Side *side; {} /* No special fixups to do. */ fixup_windows(side) Side *side; {} enable_input(side) Side *side; {} reset_misc(side) Side *side; {} /* Moving a window just involves plugging in new values. */ change_window(side, win, x, y, w, h) Side *side; int win, x, y, w, h; { if (x + w > COLS) w = COLS - x; if (y + h > LINES) h = LINES - y; if (x >= 0) { wx[win] = x; wy[win] = y; } if (w >= 0) { ww[win] = w; wh[win] = h; } } /* Actually, terminals are really "one-color", but don't take a chance on */ /* confusing the main program. */ display_colors(side) Side *side; { return 2; } white_color(side) Side *side; { return 1; } black_color(side) Side *side; { return 0; } /* Can't actually honor any color requests... */ request_color(side, name) Side *side; char *name; { return 0; } /* Only kind of input is keystrokes, and from only one "display" at that. */ get_input() { char ch; extern Side *curside; if (active_display(curside)) { draw_cursor(curside); ch = getch() & 0177; curside->reqtype = KEYBOARD; curside->reqch = ch; return TRUE; } } /* Wait for any input, don't care what it is. */ freeze_wait(side) Side *side; { refresh(); getch(); } /* Actually would be nice to do something reasonable here. */ flush_input(side) Side *side; {} /* Trivial abstraction - sometimes other routines like to ensure all output */ /* actually on the screen. */ flush_output(side) Side *side; { refresh(); } /* General window clearing. */ clear_window(side, win) Side *side; int win; { int i; if (wx[win] == 0 && wy[win] == 0 && ww[win] == COLS && wh[win] == LINES) { clear(); } else { for (i = 0; i < ww[win]; ++i) tmpbuf[i] = ' '; tmpbuf[ww[win]] = '\0'; for (i = 0; i < wh[win]; ++i) mvaddstr(wy[win]+i, wx[win], tmpbuf); } } /* No world display for curses. */ draw_bar(side, x, y, len, color) Side *side; int x, y, len, color; {} invert_box(side, vcx, vcy) Side *side; int vcx, vcy; {} /* This interfaces higher-level drawing decisions to the rendition of */ /* individual pieces of display. Note that a display mode determines */ /* whether one or two terrain characters get drawn. */ draw_terrain_row(side, x, y, buf, len, color) Side *side; int x, y, len, color; char *buf; { int i, xi = x; for (i = 0; i < len; ++i) { if (xi >= wx[side->map] + ww[side->map] - 2) break; if (cur_at(side->map, xi, y)) { addch(buf[i]); addch((side->showmode == BORDERHEX ? ' ' : buf[i])); } xi += 2; } } /* Don't just position the cursor, but also clip and return the decision. */ cur_at(win, x, y) int win, x, y; { if (x < 0 || x >= ww[win] || y < 0 || y >= wh[win]) { return FALSE; } else { move(wy[win] + y, wx[win] + x); return TRUE; } } /* Curses is never flashy... */ flash_position(side, x, y) Side *side; int x, y; {} /* Curses cursor drawing is quite easy! (but ineffective? - see input fns) */ draw_cursor_icon(side, x, y) Side *side; int x, y; { cur_at(side->map, x, y); refresh(); } /* Doesn't seem to be necessary. */ draw_hex_icon(side, win, x, y, color, ch) Side *side; int win, x, y, color; char ch; { } /* Splash a unit character onto some window. */ draw_unit_icon(side, win, x, y, u, color) Side *side; int win; int x, y, u, color; { if (cur_at(win, x, y)) { addch(utypes[u].uchar); addch(' '); /* inefficient, sigh */ } } /* Use the second position in a "hex" for identification of enemies. */ draw_side_number(side, win, x, y, n, color) Side *side; int win, x, y, n, color; { if (cur_at(win, x+1, y)) addch((n == -1) ? '`' : n + '0'); } /* Curses has enough trouble splatting stuff on the screen without doing */ /* little flashes too... */ draw_blast_icon(side, win, x, y, type, color) Side *side; int win, x, y, type, color; { } /* Unfortunately, terminals usually can't flash their screens. */ invert_whole_map(side) Side *side; {} /* Mushroom clouds don't come out real well either. */ /* This could be a little more elaborate. */ draw_mushroom(side, x, y, i) Side *side; int x, y, i; { int sx, sy; xform(side, unwrap(side, x), y, &sx, &sy); if (cur_at(side->map, sx, sy)) { addstr("##"); flush_output(side); if (i > 0) { if (cur_at(side->map, sx-1, sy+1)) addstr("####"); if (cur_at(side->map, sx-2, sy)) addstr("######"); if (cur_at(side->map, sx-1, sy-1)) addstr("####"); flush_output(side); } } } /* Indicate that bar graphs are out of the question. */ bar_graphs(side) Side *side; { return FALSE; } /* Thus this routine can be empty. */ draw_graph(side, number, amount, total, title) Side *side; int number, amount, total; { } /* Drawing text is easy, as long as we can ignore the color of it. */ /* Need to do manual clipping though. */ draw_text(side, win, x, y, str, color) Side *side; int win; int x, y, color; char *str; { int i; if (cur_at(win, x, y)) { for (i = 0; i < strlen(str); ++i) { if (x + i >= ww[win]) return; addch(str[i]); } } } /* Can't draw lines, but this will substitute, sort of. */ draw_scratchout(side, pos) Side *side; int pos; { int i; for (i = 0; i < 20; i += 2) { if (cur_at(side->sides, i, pos)) addch('-'); } } /* Beep the beeper! */ beep(side) Side *side; { putchar('\007'); } /* Most help info is printable also. */ reveal_help(side) Side *side; { notify(side, "Screen too small - writing into files instead."); do_printables(side, 0); return FALSE; } conceal_help(side) Side *side; {} /* Shut a single display down - presumably only called once. */ close_display(side) Side *side; { clear(); refresh(); endwin(); }