/* SCCS Id: @(#)winjtp.c 3.0 2000/11/12 */ /* Copyright (c) Jaakko Peltonen, 2000 */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #include "dlb.h" #ifdef SHORT_FILENAMES #include "patchlev.h" #else #include "patchlevel.h" #endif #include "func_tab.h" /* For extended commands list */ #include "display.h" /* For identifying glyph types */ #include "jtp_keys.h" #include "jtp_win.h" #include "jtp_gra.h" #include "winjtp.h" /* Interface definition, for windows.c */ struct window_procs jtp_procs = { "jtp", jtp_init_nhwindows, jtp_player_selection, jtp_askname, jtp_get_nh_event, jtp_exit_nhwindows, jtp_suspend_nhwindows, jtp_resume_nhwindows, jtp_create_nhwindow, jtp_clear_nhwindow, jtp_display_nhwindow, jtp_destroy_nhwindow, jtp_curs, jtp_putstr, jtp_display_file, jtp_start_menu, jtp_add_menu, jtp_end_menu, jtp_select_menu, jtp_message_menu, jtp_update_inventory, jtp_mark_synch, jtp_wait_synch, #ifdef CLIPPING jtp_cliparound, #endif #ifdef POSITIONBAR jtp_update_positionbar, #endif jtp_print_glyph, jtp_raw_print, jtp_raw_print_bold, jtp_nhgetch, jtp_nh_poskey, jtp_nhbell, jtp_doprev_message, jtp_yn_function, jtp_getlin, jtp_get_ext_cmd, jtp_number_pad, jtp_delay_output, /* other defs that really should go away (they're jtp specific) */ jtp_start_screen, jtp_end_screen, jtp_outrip }; int debug_putstr = 0; /* Is the player using a 'what is' command? */ int jtp_whatis_active = 0; /* Has the map window been drawn on? (eg. is it empty or not) */ int jtp_map_is_empty = 1; void win_jtp_init() { jtp_init_graphics(); } void jtp_start_screen() { } void jtp_end_screen() { } void jtp_outrip(window, how) winid window; int how; { jtp_window * tempwindow; tempwindow = jtp_find_window(window); if (!tempwindow) return; tempwindow->ending_type = how; } /* clean up and quit */ void bail(mesg) const char *mesg; { clearlocks(); jtp_exit_nhwindows(mesg); terminate(EXIT_SUCCESS); /*NOTREACHED*/ } /* Low level routines */ void jtp_raw_print(str) const char *str; { jtp_write_log_message("[NetHack]: "); jtp_write_log_message(str); jtp_write_log_message("\n"); } void jtp_raw_print_bold(str) const char *str; { jtp_write_log_message("[NetHack]: "); jtp_write_log_message(str); jtp_write_log_message("\n"); } void jtp_curs(window, x, y) winid window; register int x, y; { jtp_window * tempwindow; tempwindow = jtp_find_window(window); if (!tempwindow) return; tempwindow->curs_x = x; tempwindow->curs_y = y; } void jtp_putstr(window, attr, str) winid window; int attr; const char *str; { int i, j; jtp_window * tempwindow; char tempbuffer[1024]; anything tempid; /* JTP_DEBUG if (debug_putstr) { printf("%s\n", str); getch(); } JTP_DEBUG */ /* Display error messages immediately */ if (window == WIN_ERR) { jtp_messagebox(str); return; } tempwindow = jtp_find_window(window); if (!tempwindow) { jtp_write_log_message("ERROR: can't find window!\n"); jtp_exit_graphics(); exit(1); } /* * Each window type handles putstr separately. * Sometimes it's for convenience, sometimes for game or graphical reasons. */ /* * For windows of type NHW_MESSAGE, both the messages * and their send time are stored. * Cursor placement (curs) is not supported. */ if (tempwindow->wintype == NHW_MESSAGE) { /* Stop autopilot, except during a 'what is' command */ if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_MOVEMENT)) { jtp_move_length = 0; } /* Stop inventory (backpack) shortcut action */ jtp_is_backpack_shortcut_active = 0; /* Stop spellbook viewing */ jtp_is_spellbook_being_viewed = 0; /* * If the "what's this"-type autopilot is active, * then skip the help messages associated with NetHack's * lookat command. */ if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_WHATSTHIS)) { /* Skip help line [Please move the cursor to an unknown object.] */ if ((str) && (strncmp(str, "Please move", 11) == 0)) return; /* Skip help line [(For instructions type a ?)] */ if ((str) && (strncmp(str, "(For instru", 11) == 0)) return; /* Skip help line [Pick an object.] */ if ((str) && (strncmp(str, "Pick an obj", 11) == 0)) return; } if (str) { /* If the message is blank (whitespace), it will not be stored. */ j = 0; for (i = 0; i < strlen(str); i++) if ((str[i] != ' ') && (str[i] != 10) && (str[i] != 13)) { j = 1; break; } if (j) { /* Discard oldest message, shift others forward */ free(tempwindow->rows[tempwindow->curs_rows-1]); for (i = tempwindow->curs_rows-1; i > 0; i--) tempwindow->rows[i] = tempwindow->rows[i-1]; /* Remove leading and trailing whitespace */ j = 0; while (str[j] == ' ') j++; i = strlen(str)-1; while ((str[i]==' ')||(str[i]==10)||(str[i]==13)) i--; /* Allocate space for new message. Store string and send time. */ tempwindow->rows[0] = (int *)malloc(sizeof(int) + (i-j+2)*sizeof(char)); memcpy((char *)(tempwindow->rows[0]) + sizeof(int), str+j, i-j+1); ((char *)(tempwindow->rows[0]) + sizeof(int))[i-j+1] = '\0'; tempwindow->rows[0][0] = moves; /* Store send time in moves */ /* Make sure the new message is shown */ jtp_first_shown_message = 0; /* Play any event sounds associated with this message */ jtp_play_event_sound(str+j); } } /* Copy message to toplines[] */ strcpy(toplines, str); /* Redisplay message window */ jtp_display_nhwindow(window, FALSE); } /* * If this is a NHW_MENU window, the window must first be initialized to display * text data. If that has been done, then the text lines will be added as menu items. */ else if (tempwindow->wintype == NHW_MENU) { /* If the window is already set to menu data, it can't show text data. */ if ((tempwindow->menu) && (!tempwindow->menu->content_is_text)) return; /* Initialize menu structure, if necessary */ if (!tempwindow->menu) { tempwindow->menu = (jtp_menu *)malloc(sizeof(jtp_menu)); tempwindow->menu->items = jtp_list_new(); tempwindow->menu->prompt = NULL; tempwindow->menu->content_is_text = 1; /* Text content */ } /* Remove extra newline from the end of the string */ strncpy(tempbuffer, str, 1023); i = strlen(tempbuffer)-1; while ((i > 0) && ((tempbuffer[i] == 10) || (tempbuffer[i] == 13))) i--; tempbuffer[i+1] = '\0'; /* Add the new text line(s) as menu item(s) */ tempid.a_int = 1; /* Since text lines can't be selected anyway, these can be the same */ jtp_add_menu(window, NO_GLYPH, &tempid, 0, 0, ATR_NONE, tempbuffer, FALSE); } /* * For now, NHW_TEXT windows are handled almost like NHW_MENU windows. * This may change in the future. */ else if (tempwindow->wintype == NHW_TEXT) { /* Initialize menu structure, if necessary */ if (!tempwindow->menu) { tempwindow->menu = (jtp_menu *)malloc(sizeof(jtp_menu)); tempwindow->menu->items = jtp_list_new(); tempwindow->menu->prompt = NULL; tempwindow->menu->content_is_text = 1; /* Text content */ } /* Remove extra newline from the end of the string */ strncpy(tempbuffer, str, 1023); i = strlen(tempbuffer)-1; while ((i > 0) && ((tempbuffer[i] == 10) || (tempbuffer[i] == 13))) i--; tempbuffer[i+1] = '\0'; /* Add the new text line(s) as menu item(s) */ tempid.a_int = 1; /* Since text lines can't be selected anyway, these can be the same */ jtp_add_menu(window, NO_GLYPH, &tempid, 0, 0, ATR_NONE, tempbuffer, FALSE); } /* * The status window is the only window that supports cursor placement (curs), * but theoretically this could be extended to the map window and NHW_TEXT or * NHW_MENU windows. */ else if (tempwindow->wintype == NHW_STATUS) { /* Clear window, if necessary */ if (tempwindow->curs_y >= tempwindow->curs_rows) { for (i = 0; i < tempwindow->curs_rows; i++) for (j = 1; j < tempwindow->curs_cols; j++) tempwindow->rows[i][j] = JTP_WINCONTENT_EMPTY; tempwindow->curs_y = 0; tempwindow->curs_x = 1; } /* Output message */ for (i = 0; i < strlen(str); i++) { if ((str[i] == 10) || (str[i] == 13)) { for (j = tempwindow->curs_x; j < tempwindow->curs_cols; j++) tempwindow->rows[tempwindow->curs_y][j] = JTP_WINCONTENT_EMPTY; tempwindow->curs_y++; tempwindow->curs_x = 1; } else { tempwindow->rows[tempwindow->curs_y][tempwindow->curs_x] = str[i]; tempwindow->curs_x++; if (tempwindow->curs_x >= tempwindow->curs_cols) { tempwindow->curs_y++; tempwindow->curs_x = 1; } } if (tempwindow->curs_y >= tempwindow->curs_rows) i = strlen(str); } /* Make sure next output starts on the next line */ if (tempwindow->curs_x > 1) { for (j = tempwindow->curs_x; j < tempwindow->curs_cols; j++) tempwindow->rows[tempwindow->curs_y][j] = JTP_WINCONTENT_EMPTY; tempwindow->curs_y++; tempwindow->curs_x = 1; } } /* The status window is always redisplayed after an update */ if (tempwindow->wintype == NHW_STATUS) jtp_display_nhwindow(window, FALSE); } void jtp_get_nh_event() { } int jtp_nhgetch() { char result_key; int i, j; char tempbuffer[1024]; /* * I searched through the code, but nhgetch() * seems to be only used if the windowing system is * _not_ active (checked by !windowinited). So it doesn't * need to use map scrolling or other niceties. */ result_key = 0; while (result_key == 0) result_key = jtp_getch(); return(result_key); } int jtp_nh_poskey(x, y, mod) int *x, *y, *mod; { char result_key; int i, j; /* Play ambient music or sound effects */ jtp_play_ambient_sound(0); /* * If this call is the result of a 'what is' command, * don't use or initiate autopilot. Also, a mouse * click on the map is now an acceptable response, * since it isn't passed to the autopilot code. */ if (jtp_whatis_active) { result_key = 0; while (!result_key) { /* * Use autopilot, if active. For a 'what is' command, * the autopilot is just a series of locations to look at. */ if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_WHATSTHIS)) { if (jtp_movebuffer[0] > 0) { *y = jtp_movebuffer[0]/jtp_map_width; *x = jtp_movebuffer[0]%jtp_map_width; for (i = 0; i < jtp_move_length-1; i++) jtp_movebuffer[i] = jtp_movebuffer[i+1]; jtp_move_length--; return(0); } else { jtp_move_length = 0; return(' '); } } jtp_get_map_input(); /* Process mouse click */ result_key = jtp_whatis_mouseclick(&i, &j); if (result_key) return(result_key); else if (isok(i, j)) { *x = i; *y = j; return(0); } /* Process key press */ if (jtp_kbhit()) { result_key = jtp_getch(); result_key = jtp_translate_key(result_key); return(result_key); } if (!result_key) { jtp_draw_all_windows(); jtp_show_screen(); } } } /* * If this call is not the result of 'what is', * then allow autopilot. This handles the * default GUI interface. */ else { #ifdef JTP_INVISIBILITY_CODE if ((!jtp_map_is_empty) && (canseeself() == FALSE)) { jtp_messagebox("Can't see self!"); /* Don't use autopilot if the hero can't see self */ jtp_you_x = -1; jtp_you_y = -1; if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_MOVEMENT)) { jtp_move_length = 0; } } #endif if (jtp_kbhit()) { /* Disable autopilot because the player has made a command */ if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_MOVEMENT)) { jtp_move_length = 0; } } result_key = 0; while (!result_key) { /* * Use autopilot, if active. The 'autopilot' is just a series * of adjacent locations. If the hero is at one location, * the autopilot supplies the necessary command to move to * the next. */ if ((jtp_move_length > 0) && (jtp_autopilot_type == JTP_AUTOPILOT_MOVEMENT)) { /* Show a 'please wait'-style cursor */ jtp_show_wait_cursor(); i = jtp_movebuffer[0]/jtp_map_width; j = jtp_movebuffer[0]%jtp_map_width; if ((i == jtp_you_y-1) && (j == jtp_you_x-1)) result_key = jtp_translate_command(JTP_NHCMD_NORTHWEST); else if ((i == jtp_you_y-1) && (j == jtp_you_x)) result_key = jtp_translate_command(JTP_NHCMD_NORTH); else if ((i == jtp_you_y-1) && (j == jtp_you_x+1)) result_key = jtp_translate_command(JTP_NHCMD_NORTHEAST); else if ((i == jtp_you_y) && (j == jtp_you_x-1)) result_key = jtp_translate_command(JTP_NHCMD_WEST); else if ((i == jtp_you_y) && (j == jtp_you_x+1)) result_key = jtp_translate_command(JTP_NHCMD_EAST); else if ((i == jtp_you_y+1) && (j == jtp_you_x-1)) result_key = jtp_translate_command(JTP_NHCMD_SOUTHWEST); else if ((i == jtp_you_y+1) && (j == jtp_you_x)) result_key = jtp_translate_command(JTP_NHCMD_SOUTH); else if ((i == jtp_you_y+1) && (j == jtp_you_x+1)) result_key = jtp_translate_command(JTP_NHCMD_SOUTHEAST); else result_key = 0; if (result_key) { for (i = 0; i < jtp_move_length-1; i++) jtp_movebuffer[i] = jtp_movebuffer[i+1]; jtp_move_length--; jtp_play_command_sound(JTP_NHCMD_EAST); return(result_key); } else /* Something strange has happened along the way. Stop moving. */ { if (jtp_move_length > 0) { jtp_move_length = 0; } } } /* If the user selected a shortcut from the backpack screen, use that. */ if (jtp_is_backpack_shortcut_active) { result_key = jtp_backpack_shortcut_action; jtp_is_backpack_shortcut_active = 0; jtp_play_command_sound(jtp_find_command_nhkey_index(result_key)); return(result_key); } /* * If we got here, there was no autopilot or shortcut command. * Next, we read a mouse or keyboard command from the user. */ jtp_get_map_input(); /* Process key press */ if (jtp_kbhit()) { result_key = jtp_getch(); result_key = jtp_translate_key(result_key); jtp_play_command_sound(jtp_find_command_nhkey_index(result_key)); switch(result_key) { case '|': jtp_messagebox("Saving screenshot"); jtp_save_screenshot("scree000.pcx"); break; default: break; } return(result_key); } /* Process mouse click */ result_key = jtp_process_mouseclick(); if (result_key) { jtp_play_command_sound(jtp_find_command_nhkey_index(result_key)); return(result_key); } else { jtp_draw_all_windows(); jtp_show_screen(); } } } } /* High level routines */ void jtp_print_glyph(window, x, y, glyph) winid window; xchar x, y; int glyph; { int k; /* I hope glyphs are ONLY used in the map window and menus. jtp_window * tempwindow; tempwindow = jtp_find_window(window); if (!tempwindow) return; */ if ((y >= jtp_map_height) || (y < 0) || (x >= jtp_map_width) || (x < 1)) return; /* By this time we need to initialize tile conversion */ if (!jtp_tile_conversion_initialized) jtp_init_glyph_tiles(); if (glyph_is_cmap(glyph)) { k = glyph_to_cmap(glyph); /* S_stone glyphs need care to distinguish stone from unexplored area */ if (k == S_stone) { if ((levl[x][y].typ == STONE) || /* An actual rough stone wall */ (levl[x][y].typ == SCORR) || /* A secret passage */ (levl[x][y].typ == SDOOR)) /* A secret door */ { if (levl[x][y].seenv) jtp_mapglyph_cmap[y][x] = S_stone; else jtp_mapglyph_cmap[y][x] = JTP_WINCONTENT_GLYPH_UNEXPLORED; /* Unexplored area */ } else if ((levl[x][y].seenv) && /* Unfinished parts of room walls */ (levl[x][y].typ >= VWALL) && /* Assumes walls are in this order in rm.h */ (levl[x][y].typ <= DBWALL)) jtp_mapglyph_cmap[y][x] = S_stone; else if (levl[x][y].seenv) jtp_mapglyph_cmap[y][x] = JTP_WINCONTENT_GLYPH_NOT_VISIBLE; /* Areas that are explored but not visible (eg. dark) */ else jtp_mapglyph_cmap[y][x] = JTP_WINCONTENT_GLYPH_UNEXPLORED; /* Unexplored area */ } else { jtp_mapglyph_cmap[y][x] = k; if ((k >= S_vbeam) && (k <= S_ss4)) printf("Printed effect %d\n"); jtp_map_is_empty = 0; } /* Erase objects and monsters - hope they also get redrawn! */ jtp_mapglyph_obj[y][x] = JTP_WINCONTENT_EMPTY; jtp_mapglyph_mon[y][x] = JTP_WINCONTENT_EMPTY; } else if (glyph_is_object(glyph)) { k = glyph_to_obj(glyph); jtp_mapglyph_obj[y][x] = k; jtp_map_is_empty = 0; /* Erase monsters - hope they also get redrawn! */ jtp_mapglyph_mon[y][x] = JTP_WINCONTENT_EMPTY; } else if (glyph_is_monster(glyph)) { k = glyph_to_mon(glyph); jtp_mapglyph_mon[y][x] = k; jtp_map_is_empty = 0; } else if ((glyph >= GLYPH_ZAP_OFF) && (glyph <= GLYPH_ZAP_OFF + NUM_ZAP)) { /* A zap effect */ k = S_vbeam + ((glyph - GLYPH_ZAP_OFF) & 0x3); printf("Printing zap (%d)\n", k); jtp_mapglyph_cmap[y][x] = k; jtp_map_is_empty = 0; } /* Notify the graphics code that the map has changed */ jtp_map_changed = 1; } char jtp_yn_function(ques, choices, defchoice) const char *ques; const char *choices; char defchoice; { int i; char tempbuffer[1024]; char tempbuffer2[64]; int nanswers; int nchoice; /* jtp_messagebox("jtp_yn_function"); */ /* Separate answers string into discrete choice strings */ tempbuffer[0] = '\0'; nanswers = 0; if (choices) { for (i = 0; i < strlen(choices); i++) { if (choices[i] == '#') sprintf(tempbuffer2, "Number_"); else if (choices[i] == 27) {sprintf(tempbuffer2, "Other_"); i = strlen(choices);} else sprintf(tempbuffer2, "%c_", choices[i]); strcat(tempbuffer, tempbuffer2); nanswers++; } /* Get rid of extra underscore */ if (strlen(tempbuffer) > 0) tempbuffer[strlen(tempbuffer)-1] = '\0'; } nchoice = jtp_query(-1, -1, ques, nanswers, tempbuffer, 0); if (nanswers == 0) return(nchoice); else return(choices[nchoice]); } void jtp_getlin(ques, input) const char *ques; char *input; { jtp_get_input(-1, -1, ques, input); } int jtp_get_ext_cmd() { int i, j, k; int tempwin; int nselected; anything id; menu_item * selected; char used_accelerators[512]; char cur_accelerator, acc_found; tempwin = jtp_create_nhwindow(NHW_MENU); jtp_start_menu(tempwin); used_accelerators[0] = '\0'; /* Add extended commands as menu items */ for (i = 0; extcmdlist[i].ef_txt != NULL; i++) { /* Find an unused accelerator */ acc_found = 0; for (k = 0; k < strlen(extcmdlist[i].ef_txt); k++) { cur_accelerator = tolower(extcmdlist[i].ef_txt[k]); acc_found = 1; for (j = 0; j < strlen(used_accelerators); j++) if (used_accelerators[j] == cur_accelerator) acc_found = 0; if (!acc_found) { cur_accelerator = toupper(extcmdlist[i].ef_txt[k]); acc_found = 1; for (j = 0; j < strlen(used_accelerators); j++) if (used_accelerators[j] == cur_accelerator) acc_found = 0; } if (acc_found) break; } if (!acc_found) { /* Pick any available lowercase letter in the alphabet */ for (cur_accelerator = 'a'; cur_accelerator <= 'z'; cur_accelerator++) { acc_found = 1; for (j = 0; j < strlen(used_accelerators); j++) if (used_accelerators[j] == cur_accelerator) acc_found = 0; if (acc_found) break; } /* Pick any available uppercase letter in the alphabet */ if (!acc_found) for (cur_accelerator = 'A'; cur_accelerator <= 'Z'; cur_accelerator++) { acc_found = 1; for (j = 0; j < strlen(used_accelerators); j++) if (used_accelerators[j] == cur_accelerator) acc_found = 0; if (acc_found) break; } } /* Add found accelerator to list of used ones */ j = strlen(used_accelerators); used_accelerators[j] = cur_accelerator; used_accelerators[j+1] = '\0'; /* * All extended commands are selectable, so make sure that a_void is not zero * (it is used for 'title line' checking) */ id.a_int = i + 1; jtp_add_menu(tempwin, NO_GLYPH, &id, cur_accelerator, 0, ATR_NONE, extcmdlist[i].ef_txt, FALSE); } jtp_end_menu(tempwin, "Select a command"); nselected = jtp_select_menu(tempwin, PICK_ONE, &selected); jtp_destroy_nhwindow(tempwin); if (nselected <= 0) { free(selected); return(-1); } else { id = selected[0].item; free(selected); return(id.a_int - 1); } } void jtp_display_file(fname, complain) const char *fname; boolean complain; { dlb * f; /* Data librarian */ int nlines; char ** textlines; char tempbuffer[1024]; int i; winid window; anything tempid; menu_item * selected; /* jtp_messagebox("jtp_display_file"); jtp_messagebox(fname); */ /* Read the file */ f = dlb_fopen(fname, "r"); if (!f) { if (complain == TRUE) { sprintf(tempbuffer, "Can't open file [%s].\n", fname); jtp_messagebox(tempbuffer); } return; } nlines = 0; textlines = NULL; while (dlb_fgets(tempbuffer, 1024, f)) { nlines++; textlines = (char **)realloc(textlines, nlines*sizeof(char *)); if (!textlines) { jtp_write_log_message("ERROR: Out of memory! - location 31\n"); jtp_exit_graphics(); exit(1); } textlines[nlines-1] = (char *)malloc(strlen(tempbuffer)+1); if (!textlines[nlines-1]) { jtp_write_log_message("ERROR: Out of memory! - location 32\n"); jtp_exit_graphics(); exit(1); } strcpy(textlines[nlines-1], tempbuffer); } (void) dlb_fclose(f); /* * Make a NHW_MENU window, add each text line as a (textual) menu item. * This is a very unoptimized way of showing a text file ... */ window = jtp_create_nhwindow(NHW_MENU); for (i = 0; i < nlines; i++) jtp_putstr(window, ATR_NONE, textlines[i]); /* Display the file */ jtp_display_nhwindow(window, TRUE); /* Clean up */ jtp_destroy_nhwindow(window); for (i = 0; i < nlines; i++) free(textlines[i]); free(textlines); } void jtp_update_inventory() { } void jtp_player_selection() { jtp_select_player(); } int jtp_doprev_message() { /* jtp_messagebox("jtp_doprev_message"); */ jtp_first_shown_message++; if (jtp_first_shown_message > JTP_MAX_OLD_MESSAGES-JTP_MAX_SHOWN_MESSAGES) jtp_first_shown_message = JTP_MAX_OLD_MESSAGES-JTP_MAX_SHOWN_MESSAGES; jtp_draw_messages(jtp_find_window(WIN_MESSAGE)); jtp_show_screen(); return(0); } /* Window utility routines */ void jtp_init_nhwindows(argcp, argv) int *argcp; char **argv; { jtp_window * tempwindow; winid tempwinid; jtp_max_window_id = -1; jtp_windowlist = jtp_list_new(); jtp_show_logo_screen(); /* Success! */ iflags.window_inited = TRUE; } void jtp_exit_nhwindows(str) const char *str; { jtp_exit_graphics(); if (str) printf("%s\n", str); } winid jtp_create_nhwindow(type) int type; { int i, j; jtp_window * tempwindow; tempwindow = (jtp_window *)malloc(sizeof(jtp_window)); if (!tempwindow) { jtp_write_log_message("ERROR: Out of memory! - location 1\n"); jtp_exit_graphics(); exit(1); } jtp_max_window_id++; tempwindow->id = jtp_max_window_id; tempwindow->curs_x = 1; tempwindow->curs_y = 0; tempwindow->active = 0; /* Not active at creation time */ switch(type) { /* case NHW_BASE: tempwindow->x = 0; tempwindow->y = 0; tempwindow->width = 800; tempwindow->height = 600; tempwindow->curs_rows = 50; tempwindow->curs_cols = 80; tempwindow->rows = (int **)malloc(tempwindow->curs_rows*sizeof(int *)); for (i = 0; i < tempwindow->curs_rows; i++) tempwindow->rows[i] = (int *)malloc(tempwindow->curs_cols*sizeof(int)); tempwindow->wintype = NHW_BASE; tempwindow->menu = NULL; tempwindow->buttons = NULL; break; */ case NHW_MESSAGE: tempwindow->x = 0; tempwindow->y = 0; tempwindow->width = -1; tempwindow->height = -1; tempwindow->curs_rows = JTP_MAX_OLD_MESSAGES; tempwindow->curs_cols = -1; tempwindow->rows = (int **)malloc(tempwindow->curs_rows*sizeof(int *)); /* Message memory is allocated when the message is received */ for (i = 0; i < tempwindow->curs_rows; i++) tempwindow->rows[i] = NULL; tempwindow->wintype = NHW_MESSAGE; tempwindow->menu = NULL; tempwindow->buttons = NULL; break; case NHW_STATUS: tempwindow->x = -1; tempwindow->y = -1; tempwindow->width = 800; tempwindow->height = 100; tempwindow->curs_rows = 2; tempwindow->curs_cols = 80; tempwindow->rows = (int **)malloc(tempwindow->curs_rows*sizeof(int *)); for (i = 0; i < tempwindow->curs_rows; i++) { tempwindow->rows[i] = (int *)malloc(tempwindow->curs_cols*sizeof(int)); for (j = 0; j < tempwindow->curs_cols; j++) tempwindow->rows[i][j] = JTP_WINCONTENT_EMPTY; } tempwindow->curs_x = 1; tempwindow->curs_y = 0; tempwindow->wintype = NHW_STATUS; tempwindow->menu = NULL; tempwindow->buttons = NULL; break; case NHW_MAP: tempwindow->x = 0; tempwindow->y = 0; tempwindow->width = -1; tempwindow->height = -1; tempwindow->curs_rows = jtp_map_height; tempwindow->curs_cols = jtp_map_width; tempwindow->curs_x = 1; tempwindow->curs_y = 0; tempwindow->rows = NULL; tempwindow->wintype = NHW_MAP; tempwindow->menu = NULL; tempwindow->buttons = NULL; break; case NHW_MENU: tempwindow->x = -1; tempwindow->y = -1; tempwindow->width = -1; tempwindow->height = -1; tempwindow->curs_rows = 50; tempwindow->curs_cols = 80; tempwindow->rows = (int **)malloc(tempwindow->curs_rows*sizeof(int *)); for (i = 0; i < tempwindow->curs_rows; i++) tempwindow->rows[i] = (int *)malloc(tempwindow->curs_cols*sizeof(int)); tempwindow->wintype = NHW_MENU; tempwindow->menu = NULL; tempwindow->buttons = NULL; break; case NHW_TEXT: tempwindow->x = -1; tempwindow->y = -1; tempwindow->width = -1; tempwindow->height = -1; tempwindow->curs_rows = 50; tempwindow->curs_cols = 80; tempwindow->rows = (int **)malloc(tempwindow->curs_rows*sizeof(int *)); if (!tempwindow->rows) { jtp_write_log_message("ERROR: Out of memory! - location 2\n"); jtp_exit_graphics(); exit(1); } for (i = 0; i < tempwindow->curs_rows; i++) { tempwindow->rows[i] = (int *)malloc(tempwindow->curs_cols*sizeof(int)); if (!tempwindow->rows[i]) { jtp_write_log_message("ERROR: Out of memory! - location 3\n"); jtp_exit_graphics(); exit(1); } for (j = 0; j < tempwindow->curs_cols; j++) tempwindow->rows[i][j] = JTP_WINCONTENT_EMPTY; } tempwindow->curs_x = 1; tempwindow->curs_y = 0; tempwindow->wintype = NHW_TEXT; tempwindow->menu = NULL; tempwindow->buttons = NULL; tempwindow->ending_type = -1; break; default: return(WIN_ERR); break; } jtp_list_reset(jtp_windowlist); jtp_list_add(jtp_windowlist, tempwindow); return(tempwindow->id); } void jtp_clear_nhwindow(window) winid window; { int i, j; jtp_window * tempwindow; /* jtp_messagebox("jtp_clear_nhwindow"); */ tempwindow = jtp_find_window(window); if (!tempwindow) return; if (tempwindow->wintype == NHW_MAP) { for (i = 0; i < jtp_map_height; i++) for (j = 0; j < jtp_map_width; j++) { jtp_print_glyph(NHW_MAP, j, i, S_stone + GLYPH_CMAP_OFF); /* jtp_mapglyph_cmap[i][j] = JTP_WINCONTENT_EMPTY; */ jtp_mapglyph_obj[i][j] = JTP_WINCONTENT_EMPTY; jtp_mapglyph_mon[i][j] = JTP_WINCONTENT_EMPTY; } } else { for (i = 0; i < tempwindow->curs_rows; i++) for (j = 0; j < tempwindow->curs_cols; j++) tempwindow->rows[i][j] = JTP_WINCONTENT_EMPTY; } } void jtp_display_nhwindow(window, blocking) winid window; boolean blocking; { jtp_window * tempwindow; char tempbuffer[200]; int messages_height; menu_item * menu_list; /* Dummy pointer for displaying NHW_MENU windows */ tempwindow = jtp_find_window(window); if (!tempwindow) { jtp_write_log_message("ERROR: Invalid window!\n"); jtp_exit_graphics(); exit(1); } switch(tempwindow->wintype) { case NHW_MENU: jtp_end_menu(window, NULL); jtp_select_menu(window, PICK_NONE, &menu_list); /* if (tempwindow->width <= 0) return; jtp_draw_window(tempwindow->x, tempwindow->y, tempwindow->width, tempwindow->height); jtp_draw_menu(tempwindow->menu); jtp_draw_buttons(tempwindow->buttons); */ break; case NHW_TEXT: if (tempwindow->ending_type >= 0) jtp_show_ending(tempwindow); else { jtp_end_menu(window, NULL); jtp_select_menu(window, PICK_NONE, &menu_list); } break; case NHW_MAP: if ((jtp_map_changed) && (!jtp_map_is_empty)) { /* Update the location of the player */ jtp_old_you_x = jtp_you_x; jtp_old_you_y = jtp_you_y; jtp_you_x = u.ux; jtp_you_y = u.uy; /* If the hero has moved, center the view on him/her (optional) */ if (jtp_recenter_after_movement) if ((jtp_you_x != jtp_old_you_x) || (jtp_you_y != jtp_old_you_y)) { jtp_map_x = jtp_you_x; jtp_map_y = jtp_you_y; } /* If the hero has moved off-screen, center the view on him/her */ if ((!jtp_map_is_empty) && (!jtp_is_onscreen(jtp_you_x, jtp_you_y))) { jtp_map_x = jtp_you_x; jtp_map_y = jtp_you_y; } jtp_draw_map(tempwindow, -1, -1); tempwindow = jtp_find_window(WIN_MESSAGE); if (tempwindow) jtp_draw_messages(tempwindow); jtp_show_map_area(); } break; case NHW_STATUS: jtp_draw_status(tempwindow); /* jtp_show_screen(); */ jtp_show_status_area(); break; case NHW_MESSAGE: messages_height = jtp_draw_messages(tempwindow); jtp_show_message_area(messages_height); break; default: return; break; } /* TO DO */ } void jtp_destroy_nhwindow(window) winid window; { int i; jtp_window * tempwindow; /* jtp_messagebox("jtp_destroy_nhwindow"); */ tempwindow = jtp_find_window(window); if (!tempwindow) return; jtp_free_menu(tempwindow->menu); jtp_free_buttons(tempwindow->buttons); if (tempwindow->rows) { for (i = 0; i < tempwindow->curs_rows; i++) free(tempwindow->rows[i]); free(tempwindow->rows); } jtp_list_remove(jtp_windowlist, tempwindow); if (tempwindow->wintype == NHW_MAP) jtp_fade_out(0.2); free(tempwindow); } void jtp_start_menu(window) winid window; { jtp_window * tempwindow; tempwindow = jtp_find_window(window); if ((!tempwindow) || (tempwindow->wintype != NHW_MENU)) return; /* If the window is set to textual data, it can't display menu data */ if ((tempwindow->menu) && (tempwindow->menu->content_is_text)) return; /* Clean up previous menu */ if (tempwindow->menu) jtp_free_menu(tempwindow->menu); tempwindow->menu = (jtp_menu *)malloc(sizeof(jtp_menu)); if (!tempwindow->menu) { jtp_write_log_message("ERROR: Out of memory! - location 4\n"); jtp_exit_graphics(); exit(1); } tempwindow->menu->items = jtp_list_new(); tempwindow->menu->prompt = NULL; tempwindow->menu->content_is_text = 0; /* True menu content */ } void jtp_add_menu(window, glyph, identifier, accelerator, groupacc, attr, str, preselected) winid window; int glyph; const anything *identifier; char accelerator; char groupacc; int attr; const char *str; boolean preselected; { jtp_window * tempwindow; jtp_menuitem * tempmenuitem; char tempbuffer[1024]; tempwindow = jtp_find_window(window); if (!tempwindow) { jtp_messagebox("Error: Window ID not found!\n"); return; } if (!tempwindow->menu) { jtp_messagebox("Error: Window menu not found!\n"); return; } tempmenuitem = (jtp_menuitem *)malloc(sizeof(jtp_menuitem)); if (!tempmenuitem) { jtp_write_log_message("ERROR: Out of memory! - location 5\n"); jtp_exit_graphics(); exit(1); } if ((!identifier) || (!identifier->a_void)) tempmenuitem->count = JTP_NOT_SELECTABLE; else { tempmenuitem->id = *identifier; tempmenuitem->count = -1; } if (preselected) tempmenuitem->selected = TRUE; else tempmenuitem->selected = FALSE; tempmenuitem->accelerator = accelerator; tempmenuitem->glyph = glyph; if (accelerator) sprintf(tempbuffer, "[%c] - %s", accelerator, str); else sprintf(tempbuffer, "%s", str); tempmenuitem->text = (char *)malloc(strlen(tempbuffer)+1); if (!tempmenuitem->text) { jtp_write_log_message("ERROR: Out of memory! - location 6\n"); jtp_exit_graphics(); exit(1); } memcpy(tempmenuitem->text, tempbuffer, strlen(tempbuffer)+1); jtp_list_reset(tempwindow->menu->items); while (jtp_list_current(tempwindow->menu->items)) jtp_list_advance(tempwindow->menu->items); jtp_list_add(tempwindow->menu->items, tempmenuitem); /* jtp_messagebox(tempmenuitem->text); */ } void jtp_end_menu(window, prompt) winid window; const char *prompt; { jtp_window * tempwindow; jtp_button * tempbutton; jtp_menuitem * tempmenuitem; int n_accelerators = 0; int temp_accelerator; int used_accelerators[1024]; char tempbuffer[1024]; tempwindow = jtp_find_window(window); if (!tempwindow) return; if (!tempwindow->menu) return; if (prompt) { tempwindow->menu->prompt = (char *)malloc(strlen(prompt)+1); if (!tempwindow->menu->prompt) { jtp_write_log_message("ERROR: Out of memory! - location 7\n"); jtp_exit_graphics(); exit(1); } memcpy(tempwindow->menu->prompt, prompt, strlen(prompt)+1); } else tempwindow->menu->prompt = NULL; /* Clean up previous buttons */ if (tempwindow->buttons) jtp_free_buttons(tempwindow->buttons); tempwindow->buttons = jtp_list_new(); /* If the content is textual, add a Continue button */ if (tempwindow->menu->content_is_text) { tempbutton = (jtp_button *)malloc(sizeof(jtp_button)); if (!tempbutton) { jtp_write_log_message("ERROR: Out of memory! - location 8\n"); jtp_exit_graphics(); exit(1); } tempbutton->text = (char *)malloc(strlen("Continue")+1); if (!tempbutton->text) { jtp_write_log_message("ERROR: Out of memory! - location 9\n"); jtp_exit_graphics(); exit(1); } strcpy(tempbutton->text, "Continue"); tempbutton->id = 0; tempbutton->accelerator = '\r'; /* Enter */ jtp_list_reset(tempwindow->buttons); jtp_list_add(tempwindow->buttons, tempbutton); } else /* For non-textual (possibly selectable) content, add Accept and Cancel buttons */ { /* Add a Cancel button */ tempbutton = (jtp_button *)malloc(sizeof(jtp_button)); if (!tempbutton) { jtp_write_log_message("ERROR: Out of memory! - location 8\n"); jtp_exit_graphics(); exit(1); } tempbutton->text = (char *)malloc(strlen("Continue")+1); if (!tempbutton->text) { jtp_write_log_message("ERROR: Out of memory! - location 9\n"); jtp_exit_graphics(); exit(1); } strcpy(tempbutton->text, "Cancel"); tempbutton->id = 0; tempbutton->accelerator = 27; /* ESC */ jtp_list_reset(tempwindow->buttons); jtp_list_add(tempwindow->buttons, tempbutton); /* Add an Accept button */ tempbutton = (jtp_button *)malloc(sizeof(jtp_button)); if (!tempbutton) { jtp_write_log_message("ERROR: Out of memory! - location 10\n"); jtp_exit_graphics(); exit(1); } tempbutton->text = (char *)malloc(strlen("Accept")+1); if (!tempbutton->text) { jtp_write_log_message("ERROR: Out of memory! - location 11\n"); jtp_exit_graphics(); exit(1); } strcpy(tempbutton->text, "Accept"); tempbutton->id = 1; tempbutton->accelerator = '\r'; /* Enter */ jtp_list_reset(tempwindow->buttons); jtp_list_add(tempwindow->buttons, tempbutton); } /* * If the content is not textual, make sure that each selectable * item has a keyboard accelerator */ if (!tempwindow->menu->content_is_text) { n_accelerators = 0; used_accelerators[0]='\0'; jtp_list_reset(tempwindow->menu->items); tempmenuitem = (jtp_menuitem *)jtp_list_current(tempwindow->menu->items); while (tempmenuitem) { if (tempmenuitem->count != JTP_NOT_SELECTABLE) { temp_accelerator = tempmenuitem->accelerator; if (temp_accelerator <= 0) { temp_accelerator = jtp_find_menu_accelerator(tempmenuitem->text, used_accelerators); if (temp_accelerator > 0) { tempmenuitem->accelerator = temp_accelerator; sprintf(tempbuffer, "[%c] - %s", temp_accelerator, tempmenuitem->text); /* jtp_write_log_message(tempbuffer); jtp_write_log_message("\n"); */ free(tempmenuitem->text); tempmenuitem->text = (char *)malloc(strlen(tempbuffer)+1); strcpy(tempmenuitem->text, tempbuffer); } } if (temp_accelerator > 0) { used_accelerators[n_accelerators] = temp_accelerator; used_accelerators[n_accelerators+1] = '\0'; n_accelerators++; } } jtp_list_advance(tempwindow->menu->items); tempmenuitem = (jtp_menuitem *)jtp_list_current(tempwindow->menu->items); } } /* jtp_messagebox("Menu ready."); */ } int jtp_select_menu(window, how, menu_list) winid window; int how; menu_item **menu_list; { jtp_window * tempwindow; jtp_menuitem * tempmenuitem; int selectedbutton, n_selected; if ((window == WIN_INVEN) && (how == PICK_NONE)) { jtp_view_inventory(); *menu_list = NULL; return(-1); } tempwindow = jtp_find_window(window); if (!tempwindow) { jtp_messagebox("ERROR: Can't find window for menu selection!"); return; } if (!tempwindow->menu) { jtp_messagebox("ERROR: Window does not have a menu!"); return; } tempwindow->menu->selectiontype = how; /* jtp_messagebox("Entering menu selection");*/ jtp_get_menu_coordinates(tempwindow); /* jtp_messagebox("Coordinates found");*/ selectedbutton = jtp_get_menu_selection(tempwindow); if (selectedbutton == 0) /* Selected cancel */ { /* jtp_messagebox("Selected cancel"); */ *menu_list = NULL; return(-1); } else { n_selected = 0; jtp_list_reset(tempwindow->menu->items); tempmenuitem = (jtp_menuitem *)jtp_list_current(tempwindow->menu->items); *menu_list = NULL; while (tempmenuitem) { if (tempmenuitem->selected == TRUE) { n_selected++; *menu_list = (menu_item *)realloc(*menu_list, n_selected*sizeof(menu_item)); (*menu_list)[n_selected-1].item = tempmenuitem->id; (*menu_list)[n_selected-1].count = tempmenuitem->count; } jtp_list_advance(tempwindow->menu->items); tempmenuitem = (jtp_menuitem *)jtp_list_current(tempwindow->menu->items); } return(n_selected); } } void jtp_suspend_nhwindows(str) const char *str; { jtp_messagebox("Suspending the game."); if (str) jtp_messagebox(str); } void jtp_resume_nhwindows() { jtp_messagebox("Resuming the game."); } char jtp_message_menu(let, how, mesg) char let; int how; const char *mesg; { genl_message_menu(let, how, mesg); } void jtp_mark_synch() { } void jtp_wait_synch() { } void jtp_cliparound(x, y) int x; int y; { } void jtp_update_positionbar(features) char *features; { } void jtp_nhbell() { } void jtp_number_pad(state) int state; { } void jtp_delay_output() { } /* End of winjtp.c */