home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- * spredio.c
- *
- * Routines for screen painting and message generation
- **********************************************************************
- This file is part of
-
- STK -- The sprite toolkit -- version 1.0
-
- Copyright (C) Jari Karjala 1990
-
- The sprite toolkit (STK) is a FreeWare toolkit for creating high
- resolution sprite graphics with PCompatible hardware. This toolkit
- is provided as is without any warranty or such thing. See the file
- COPYING for further information.
-
- **********************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <conio.h>
- #include <graphics.h>
-
- #include "grtypes.h"
- #include "gr.h"
- #include "mouse.h"
-
- #include "spred.h"
- #include "spredio.h"
-
- /** pointer already disabled **/
- int pointer_disabled = 0;
-
- /** previously selected button **/
- int prev_button = 0;
-
-
- /**********************************************************************
- * Screen items
- **********************************************************************/
- typedef struct _screen_item {
- int x1,y1,x2,y2; /* positive from left/top, negative from right/bot */
- MSG msg;
- char *text; /* max 14 char. (14*8<116) */
- int hotkey;
- } SCREEN_ITEM;
-
- #define LEF(sip) ((sip)->x1>=0 ? (sip)->x1 : gr_max_x + (sip)->x1)
- #define RIG(sip) ((sip)->x2>=0 ? (sip)->x2 : gr_max_x + (sip)->x2)
- #define TOP(sip) ((sip)->y1>=0 ? (sip)->y1 : gr_max_y + (sip)->y1)
- #define BOT(sip) ((sip)->y2>=0 ? (sip)->y2 : gr_max_y + (sip)->y2)
-
- /**********************************************************************
- * The screen layout definition.
- * - The first entry must be big bitmap,
- * - the second the shape button,
- * - the third mask button (must be as large as the shape button),
- * - the rest are little text buttons.
- **********************************************************************/
- SCREEN_ITEM screen_def[] = {
- 120, 0, -1, 240, MSG_NONE, NULL, -1,
- 0, 0, 120, 120, MSG_ACTIVATE_SHAPE, "Shape", 's',
- 0, 120, 120, 240, MSG_ACTIVATE_MASK, "Mask", 'm',
- /*** first column buttons ***/
- 0,-100, 118, -90, MSG_CLEAR, "Clear", 256*46,
- 0, -88, 118, -78, MSG_LOAD, "Load", 256*38,
- 0, -76, 118, -66, MSG_SAVE, "Save", 256*31,
- 0, -64, 118, -54, MSG_NEXT, "Next Sprite", 256*49,
- 0, -52, 118, -42, MSG_PREV, "Prev Sprite", 256*25,
- 0, -40, 118, -30, MSG_EXIT, "Save & Exit", 256*45,
- 0, -28, 118, -16, MSG_QUIT, "Quit", 256*16,
- /*** second column buttons ***/
- 120,-100, 238, -90, MSG_INVERT, "Invert", 'i',
- 120, -88, 238, -78, MSG_FATTER, "Make Fatter", 'f',
- 120, -76, 238, -66, MSG_THINNER, "Make Thinner", 't',
- 120, -64, 238, -54, MSG_OVERLAY, "Overlay", 'o',
- 120, -52, 238, -42, MSG_NONE, "", -1,
- 120, -40, 238, -30, MSG_COPY_TO_MASK, "Shape -> Mask",-1,
- 120, -28, 238, -16, MSG_COPY_TO_SHAPE, "Mask -> Shape",-1,
- /*** third column buttons ***/
- 240,-100, 358, -90, MSG_HFLIP, "Horiz Flip", 'h',
- 240, -88, 358, -78, MSG_VFLIP, "Vert Flip", 'v',
- 240, -76, 358, -66, MSG_HMIRROR, "Horiz Mirror", -1,
- 240, -64, 358, -54, MSG_VMIRROR, "Vert Mirror", -1,
- 240, -52, 358, -42, MSG_ROTATE, "Rotate", -1,
- 240, -40, 358, -30, MSG_ROTATE90, "Rotate 90deg", 'r',
- 240, -28, 358, -16, MSG_NONE, "", -1,
-
- 0, 0, 0, 0, 0, NULL
- };
-
-
- /**********************************************************************
- * Print the message, clear old message
- **********************************************************************/
- void message(char *s,...)
- {
- char buf[100];
- va_list argptr;
-
- va_start(argptr,100);
- vsprintf(buf,s,argptr);
- va_end(argptr);
-
- setfillstyle(EMPTY_FILL,0);
- bar(0,gr_max_y-10, gr_max_x, gr_max_y);
- moveto(0,gr_max_y-10);
- mouse_hide_pointer();
- gr_printf(buf);
- mouse_show_pointer();
- }
-
- /**********************************************************************
- * Draw the given button type screen item
- **********************************************************************/
- void draw_button_item(SCREEN_ITEM *sip)
- {
- int oldcolor;
-
- oldcolor = getcolor();
- setfillstyle(SOLID_FILL,getmaxcolor());
- bar(LEF(sip), TOP(sip), RIG(sip), BOT(sip));
- settextstyle(DEFAULT_FONT,0,1);
- setcolor(0);
- outtextxy(LEF(sip)+((RIG(sip)-LEF(sip)-textwidth(sip->text)) >> 1),
- TOP(sip)+((BOT(sip)-TOP(sip)-textheight(sip->text)) >> 1)+1,
- sip->text);
- setcolor(oldcolor);
- setfillstyle(EMPTY_FILL,0);
- }
-
- /**********************************************************************
- * highlight the given button type screen item
- **********************************************************************/
- void highlight_button_item(SCREEN_ITEM *sip)
- {
- int oldcolor;
-
- mouse_hide_pointer();
- oldcolor = getcolor();
- setwritemode(1);
- rectangle(LEF(sip)+1, TOP(sip)+1, RIG(sip)-1, BOT(sip)-1);
- setwritemode(0);
- setcolor(oldcolor);
- mouse_show_pointer();
- }
-
- /**********************************************************************
- * Draw a point in the i:th map (shape/mask) of sprite.
- * If i & DOT_OVERLAY then the other map is overlayed.
- **********************************************************************/
- void draw_point(SPRED_DATA *sdp, int x, int y, int i)
- {
- int xofs, yofs, overlay, max_col;
-
- max_col = getmaxcolor();
- overlay = (i & DOT_OVERLAY);
- i &= 0xFF;
-
- if (!pointer_disabled)
- mouse_hide_pointer();
-
- /** draw the little bitmap **/
- xofs = (RIG(&screen_def[1]) - LEF(&screen_def[1]) - sdp->w) / 2;
- yofs = (BOT(&screen_def[1]) - TOP(&screen_def[1]) - sdp->h) / 2;
- if (i == SPR_SHAPE)
- putpixel(x+xofs, y+yofs,
- max_col*sdp->maps[i][x][y]);
- else
- putpixel(x+xofs, y+yofs+TOP(&screen_def[2]),
- max_col*sdp->maps[i][x][y]);
-
- /** draw the big bitmap **/
- xofs = sdp->wo + x*sdp->ws;
- yofs = sdp->ho + y*sdp->hs;
-
- if (i==sdp->map) {
- if (sdp->maps[i][x][y]!=DOT_BACKGROUND) {
- setfillstyle(SOLID_FILL, max_col);
- bar(xofs, yofs, xofs + sdp->ws - 1, yofs + sdp->hs - 1);
- }
- else {
- setfillstyle(EMPTY_FILL, 0);
- bar(xofs, yofs, xofs + sdp->ws - 1, yofs + sdp->hs - 1);
-
- if (sdp->ws > 4) { /** no corner dots, if grid too small **/
- putpixel(xofs, yofs, max_col);
- putpixel(xofs + sdp->ws-1, yofs, max_col);
- putpixel(xofs, yofs + sdp->hs - 1, max_col);
- putpixel(xofs + sdp->ws - 1, yofs + sdp->hs - 1, max_col);
- }
- }
- }
- /** draw the other map overlayed, if requested **/
- if (overlay) {
- int s;
- s = sdp->ws / 3;
- if (sdp->maps[ (i==0) ][x][y]!=0)
- setfillstyle(SOLID_FILL, max_col);
- else
- setfillstyle(EMPTY_FILL, 0);
- bar(xofs + s, yofs + s, xofs + sdp->ws - s , yofs + sdp->hs - s);
- }
-
- if (!pointer_disabled)
- mouse_show_pointer();
- }
-
- /**********************************************************************
- * Draw the ind:th map (shape/mask) of the given sprite (bigmap too,
- * if active).
- * Pointer is disabled if it is inside map area, otherwise it is
- * only restricted into menu area.
- **********************************************************************/
- void draw_map(SPRED_DATA *sdp, int ind)
- {
- int i,j, x, y;
-
- mouse_get_pointer_xy(&x,&y);
- mouse_set_pointer_shape(0,0,mouse_pointer_hourglass);
- if (y>BOT(&screen_def[0])) {
- pointer_disabled = 1;
- mouse_set_pointer_window(0,BOT(&screen_def[0]),gr_max_x,gr_max_y);
- }
-
- if (sdp->map == ind && 0xFF)
- rectangle(sdp->wo-1, sdp->ho-1,
- sdp->wo + sdp->w*sdp->ws, sdp->ho + sdp->h*sdp->hs);
-
- moveto(LEF(&screen_def[0])+2, TOP(&screen_def[0])+2);
- if (sdp->map==SPR_SHAPE)
- gr_puts("Shape bitmap");
- else
- gr_puts("Mask bitmap ");
-
- for (i=0; i<sdp->h; i++)
- for (j=0; j<sdp->w; j++)
- draw_point(sdp, j, i, ind);
-
- pointer_disabled = 0;
- mouse_set_pointer_window(0,0,getmaxx(),getmaxy());
- mouse_set_pointer_shape(1,1,mouse_pointer_arrow);
- }
-
- /**********************************************************************
- * Draw the screen layout. Must be called before any other draw function.
- **********************************************************************/
- void draw_screen(SPRED_DATA *sdp)
- {
- int i;
-
- mouse_hide_pointer();
-
- bar(LEF(&screen_def[0])+1, TOP(&screen_def[0])+1,
- RIG(&screen_def[0])-1, BOT(&screen_def[0])-1);
- rectangle(LEF(&screen_def[0]), TOP(&screen_def[0]),
- RIG(&screen_def[0]), BOT(&screen_def[0]));
-
- bar(LEF(&screen_def[1])+1, TOP(&screen_def[1])+1,
- RIG(&screen_def[1])-1, BOT(&screen_def[1])-1);
- outtextxy(LEF(&screen_def[1])+2, TOP(&screen_def[1])+2,
- screen_def[1].text);
- rectangle(LEF(&screen_def[1]), TOP(&screen_def[1]),
- RIG(&screen_def[1]), BOT(&screen_def[1]));
-
- bar(LEF(&screen_def[2])+1, TOP(&screen_def[2])+1,
- RIG(&screen_def[2])-1, BOT(&screen_def[2])-1);
- outtextxy(LEF(&screen_def[2])+2, TOP(&screen_def[2])+2,
- screen_def[2].text);
- rectangle(LEF(&screen_def[2]), TOP(&screen_def[2]),
- RIG(&screen_def[2]), BOT(&screen_def[2]));
-
- i = 3;
- while((screen_def[i].x1 | screen_def[i].x2 |
- screen_def[i].y1 | screen_def[i].y2) != 0)
- draw_button_item(&screen_def[i++]);
-
- sdp->hs = (BOT(&screen_def[0]) - TOP(&screen_def[0])) / (sdp->h+1);
- sdp->ws = (RIG(&screen_def[0]) - LEF(&screen_def[0])) / (sdp->w+1);
- if (sdp->ws < sdp->hs) /** take smallest **/
- sdp->hs = sdp->ws;
- else
- sdp->ws = sdp->hs;
- if (sdp->hs<3) /** no smaller than 3 **/
- sdp->hs = 3;
-
- sdp->wo = LEF(&screen_def[0]) +
- (RIG(&screen_def[0]) - LEF(&screen_def[0]) - sdp->w*sdp->ws)/2;
-
- sdp->ho = (BOT(&screen_def[0]) - TOP(&screen_def[0]) - sdp->h*sdp->hs)/2;
-
- draw_map(sdp, SPR_SHAPE);
- draw_map(sdp, SPR_MASK);
-
- mouse_show_pointer();
- prev_button = 0; /** no buttons selected **/
- }
-
-
- /**********************************************************************
- * Find the screen item in the given position form the screen_def array.
- * Return: index into array or negative if no match.
- **********************************************************************/
- int find_clicked_item(int x, int y)
- {
- int i;
-
- i = 0;
- while((screen_def[i].x1 | screen_def[i].x2 |
- screen_def[i].y1 | screen_def[i].y2) != 0) {
- if (x>LEF(&screen_def[i]) && y>TOP(&screen_def[i]) &&
- x<RIG(&screen_def[i]) && y<BOT(&screen_def[i]))
- return i;
- i++;
- }
- return -1;
- }
-
- /**********************************************************************
- * Find the screen item matching the given hotkey.
- * Return: index into array or negative if no match.
- **********************************************************************/
- int find_hotkeyed_item(int ch)
- {
- int i;
-
- i = 0;
- while((screen_def[i].x1 | screen_def[i].x2 |
- screen_def[i].y1 | screen_def[i].y2) != 0) {
- if (screen_def[i].hotkey == ch)
- return i;
- i++;
- }
- return -1;
- }
-
- /**********************************************************************
- * Checks for user interaction.
- *
- * Return: The event message, and the *x & *y contain the click point
- * in big map coordinates (ie 0..sdp->w-1 and 0..sdp->h-1).
- **********************************************************************/
- MSG get_msg(SPRED_DATA *sdp, int *xp, int *yp)
- {
- int buttons, i;
- MSG msg = MSG_NONE;
-
- if (prev_button > 0) {
- highlight_button_item(&screen_def[prev_button]);
- prev_button = 0;
- }
-
- buttons = mouse_get_buttons();
- mouse_get_pointer_xy(xp,yp);
- if (buttons!=0) {
- i = find_clicked_item(*xp, *yp);
- if (i>0) {
- prev_button = i;
- highlight_button_item(&screen_def[prev_button]);
- msg = screen_def[i].msg;
- }
- else if (i==0) {
- switch (buttons) {
- case BUTTON_LEFT : msg = MSG_BTN1_CLICK;
- break;
- case BUTTON_RIGHT : msg = MSG_BTN3_CLICK;
- break;
- case BUTTON_MS_MIDDLE:
- case BUTTON_MIDDLE : msg = MSG_BTN2_CLICK;
- break;
- }
- *xp = (*xp - sdp->wo)/sdp->ws;
- *yp = (*yp - sdp->ho)/sdp->hs;
-
- if (*xp<0 || *yp<0 || *xp >= sdp->w || *yp >= sdp->h)
- msg = MSG_NONE; /* out of big bitmap */
- }
- }
- else if (kbhit()) {
- int ch = getch();
-
- if (ch==0) /** special key, put significant part into high byte **/
- ch = getch()<<8;
-
- i = find_hotkeyed_item(ch);
- if (i>0) {
- prev_button = i;
- highlight_button_item(&screen_def[prev_button]);
- msg = screen_def[i].msg;
- }
- }
- return msg;
- }
-