541 lines
15 KiB
Plaintext
541 lines
15 KiB
Plaintext
_AN ICON EDITOR_
|
|
by Keith Weiskamp and Loren Heiny
|
|
|
|
|
|
[LISTING ONE]
|
|
|
|
/* iconed.c -- a special purpose icon editor.
|
|
*
|
|
* This program allows you to interactively edit icons that
|
|
* can be used in a graphics program. You can create an icon,
|
|
* edit an existing one, or save an icon pattern to a file. The
|
|
* program requires a mouse. The icon files produced are of the
|
|
* form:
|
|
* ICONWIDTH ICONHEIGHT
|
|
* one row of icon pattern
|
|
* next row of icon pattern
|
|
* . . .
|
|
* last row of icon pattern
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <conio.h>
|
|
#include <graphics.h>
|
|
#include <stdarg.h>
|
|
#include <alloc.h>
|
|
#include "mouse.h" /* mouse and keyboard routines */
|
|
|
|
#define BIGICONLEFT 20 /* left side of the big icon pattern */
|
|
#define BIGICONTOP 50 /* top side of the big icon pattern */
|
|
#define BIGBITSIZE 8 /* big bits are 8 pixels in size */
|
|
#define ICONWIDTH 16 /* an icon is a 16x16 pattern */
|
|
#define ICONHEIGHT 16
|
|
#define ICONLEFT 400 /* small icon pattern located here */
|
|
#define ESC 27 /* the value of the ESC key */
|
|
|
|
/* Here are the functions used in iconed.c: */
|
|
|
|
void draw_enlarged_icon(void);
|
|
void toggle_bigbit(int x, int y);
|
|
void toggle_icons_bit(int x, int y);
|
|
void init_bigbit(void);
|
|
void toggle_cursor(int x, int y);
|
|
void save_icon(void);
|
|
int read_icon(void);
|
|
void init_graphics(void);
|
|
void show_icon(void);
|
|
|
|
/* The global variables */
|
|
|
|
void *bigbit; /* points to image of a big bit */
|
|
/* holds icon pattern */
|
|
unsigned char icon[ICONHEIGHT][ICONWIDTH];
|
|
|
|
void main()
|
|
{
|
|
int x, y;
|
|
int c;
|
|
|
|
read_icon(); /* read in an icon file */
|
|
init_graphics();
|
|
/* initialize mouse */
|
|
if (!initmouse()) { /* must have mouse */
|
|
restorecrtmode();
|
|
printf("\nMouse not installed");
|
|
printf("\nQuitting the Icon Editor");
|
|
exit(1);
|
|
}
|
|
draw_enlarged_icon(); /* an empty big icon pattern */
|
|
show_icon(); /* Draw the icon */
|
|
|
|
hidemouse(); /* mouse cursor must be turned off */
|
|
/* before writing to screen */
|
|
outtextxy(BIGICONLEFT, 10, "Press ESC when finished ...");
|
|
outtextxy(BIGICONLEFT, BIGICONTOP-20, "Enlarged Icon");
|
|
outtextxy(ICONLEFT, BIGICONTOP-20, "Actual Icon");
|
|
showmouse(); /* redisplay mouse cursor */
|
|
|
|
/* get input from mouse/keyboard */
|
|
while ((c=waitforinput(LEFT_BUTTON)) != ESC) {
|
|
if (c < 0) { /* if true mouse button pressed */
|
|
getmousecoords(&x, &y); /* get current position */
|
|
toggle_bigbit(x, y); /* toggle big bit */
|
|
}
|
|
}
|
|
|
|
hidemouse(); /* turn mouse off and then get out */
|
|
closegraph(); /* of graphics mode */
|
|
printf("Do you want to save this icon to a file? (y) ");
|
|
if (getch() != 'n')
|
|
save_icon();
|
|
}
|
|
|
|
|
|
void draw_enlarged_icon(void)
|
|
{
|
|
/*
|
|
* This function draws an enlarged view of the icon pattern.
|
|
* You can click a big bit in this pattern to toggle the
|
|
* corresponding icons on and off in the actual icon. The
|
|
* icon is drawn at BIGICONLEFT, BIGICONTOP, to right, bottom.
|
|
*/
|
|
int i;
|
|
int right,bottom;
|
|
|
|
setlinestyle(DOTTED_LINE, 0, NORM_WIDTH);
|
|
right = 2 * (BIGICONLEFT + (ICONWIDTH-1) *
|
|
(BIGBITSIZE + NORM_WIDTH));
|
|
bottom = BIGICONTOP + ICONHEIGHT * (BIGBITSIZE + NORM_WIDTH);
|
|
|
|
hidemouse(); /* draw vertical and horizonatal dashed */
|
|
for (i=0; i<=ICONHEIGHT; i++)
|
|
line(BIGICONLEFT, BIGICONTOP+i*(BIGBITSIZE+NORM_WIDTH),
|
|
right, BIGICONTOP+i*(BIGBITSIZE+NORM_WIDTH));
|
|
for (i=0; i<=ICONWIDTH; i++)
|
|
line(BIGICONLEFT+2*(i*(BIGBITSIZE+NORM_WIDTH)), BIGICONTOP,
|
|
BIGICONLEFT+2*(i*(BIGBITSIZE+NORM_WIDTH)), bottom);
|
|
showmouse();
|
|
init_bigbit(); /* create the big bit image */
|
|
}
|
|
|
|
|
|
void init_bigbit(void)
|
|
{
|
|
/* This function creates the image of a single big bit. This
|
|
* image is used to toggle the big bits whenever the user
|
|
* clicks on the big icon pattern.
|
|
*/
|
|
int bbx, bby;
|
|
int i,j;
|
|
|
|
bbx = BIGICONLEFT;
|
|
bby = BIGICONTOP; /* corner of the big icon */
|
|
|
|
hidemouse(); /* hide the mouse before drawing */
|
|
for (j=bby+1; j<=bby+BIGBITSIZE; j++) {
|
|
for (i=bbx+1; i<=bbx+2*BIGBITSIZE; i++) {
|
|
putpixel(i,j,getmaxcolor());
|
|
}
|
|
}
|
|
|
|
/* Set aside memory for the big bit image and then use
|
|
getimage() to capture its image. */
|
|
|
|
bigbit = malloc(imagesize(bbx,bby,bbx+2*BIGBITSIZE,
|
|
bby+BIGBITSIZE));
|
|
getimage(bbx+1,bby+1,bbx+2*BIGBITSIZE,bby+BIGBITSIZE,
|
|
bigbit);
|
|
|
|
/* Erase the big bit by exclusive ORing it with itself */
|
|
|
|
putimage(bbx+1, bby+1, bigbit, XOR_PUT);
|
|
showmouse(); /* turn the mouse back on */
|
|
}
|
|
|
|
|
|
void toggle_bigbit(int x, int y)
|
|
{
|
|
/*
|
|
* This function toggles a big bit and the corresponding pixel
|
|
* in the icon pattern. The x and y coordinates specify the
|
|
* mouse position.
|
|
*/
|
|
int i, j;
|
|
int line1, line2, col1, col2;
|
|
|
|
for (j=0; j<ICONHEIGHT; j++) {
|
|
line1 = BIGICONTOP+j*(BIGBITSIZE+NORM_WIDTH);
|
|
line2 = BIGICONTOP+(j+1)*(BIGBITSIZE+NORM_WIDTH);
|
|
if (line1 <= y && y < line2) {
|
|
for (i=0; i<ICONWIDTH; i++) {
|
|
col1 = BIGICONLEFT+2*(i*(BIGBITSIZE+NORM_WIDTH));
|
|
col2 = BIGICONLEFT+2*((i+1)*
|
|
(BIGBITSIZE+NORM_WIDTH));
|
|
if (col1 <= x && x < col2) {
|
|
hidemouse();
|
|
putimage(col1+1,line1+1,bigbit,XOR_PUT);
|
|
showmouse();
|
|
toggle_icons_bit(i, j);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void toggle_icons_bit(int x, int y)
|
|
{
|
|
/*
|
|
* This function toggles a single pixel in the icon pattern.
|
|
* The pixel's color and value is changed in the icon array.
|
|
* Arguments x and y are between 0 and ICONWIDTH or ICONHEIGHT.
|
|
* The array icon saves the icon pattern. If a location is set
|
|
* to 1, the corresponding pixel in the icon is displayed.
|
|
*/
|
|
hidemouse();
|
|
/* if pixel is not black, make it black */
|
|
if (getpixel(2*x+ICONLEFT,BIGICONTOP+y) != BLACK) {
|
|
putpixel(2*x+ICONLEFT,BIGICONTOP+y,BLACK);
|
|
putpixel(2*x+1+ICONLEFT,BIGICONTOP+y,BLACK);
|
|
icon[y][x] = 0;
|
|
}
|
|
else { /* draw all pixels on with the max color */
|
|
putpixel(2*x+ICONLEFT,BIGICONTOP+y,getmaxcolor());
|
|
putpixel(2*x+1+ICONLEFT,BIGICONTOP+y,getmaxcolor());
|
|
icon[y][x] = 1;
|
|
}
|
|
showmouse();
|
|
}
|
|
|
|
|
|
void save_icon(void)
|
|
{
|
|
/* This function writes the icon pattern to a file. The user
|
|
* is prompted for the filename. The format of the file is
|
|
* presented at the top of the iconed.c file.
|
|
*/
|
|
char filename[80];
|
|
FILE *iconfile;
|
|
int i, j;
|
|
|
|
printf("\nEnter the file name to store the icon in: ");
|
|
scanf("%s",filename);
|
|
if ((iconfile = fopen(filename,"w")) == NULL) {
|
|
printf("Could not open file.\n");
|
|
return;
|
|
}
|
|
/* Write the header to the file */
|
|
fprintf(iconfile, "%d %d\n", ICONWIDTH, ICONHEIGHT);
|
|
|
|
for (j=0; j<ICONHEIGHT; j++) { /* Write the icon */
|
|
for (i=0; i<ICONWIDTH; i++) /* pattern to a file */
|
|
fprintf(iconfile, "%x ", icon[j][i]);
|
|
fprintf(iconfile, "\n");
|
|
}
|
|
fclose(iconfile);
|
|
}
|
|
|
|
|
|
int read_icon(void)
|
|
{
|
|
/* This function reads an icon file into the icon array and
|
|
* calls show_icon() to turn the appropriate pixels on. If the
|
|
* file header doesn't match ICONWIDTH and ICONHEIGHT, the
|
|
* the file is invalid and the icon is not read. The function
|
|
* returns a 0 if a file is not read; otherwise 1 is returned.
|
|
*/
|
|
char filename[80];
|
|
FILE *iconfile;
|
|
int i, j;
|
|
int width, height;
|
|
|
|
for (j=0; j<ICONHEIGHT; j++) { /* Initialize icon array */
|
|
for (i=0; i<ICONWIDTH; i++) /* to all blanks */
|
|
icon[j][i] = 0;
|
|
}
|
|
|
|
printf("\n\n----------- ICON EDITOR -------------\n\n");
|
|
printf("Do you want to edit an existing icon? (y) ");
|
|
|
|
if (getch() == 'n')
|
|
return(0);
|
|
|
|
printf("\nEnter name of the file to read the icon from: ");
|
|
scanf("%s",filename);
|
|
if ((iconfile = fopen(filename,"r")) == NULL) {
|
|
printf("Cannot open file.\n");
|
|
return(0); /* return a failure flag */
|
|
}
|
|
/* Read first line of the icon file. It should contain two
|
|
numbers that are equal to ICONWIDTH and ICONHEIGHT.
|
|
*/
|
|
fscanf(iconfile,"%d %d", &width, &height);
|
|
if (width != ICONWIDTH || height != ICONHEIGHT) {
|
|
printf("Incompatible icon file.\n");
|
|
return(0); /* return a failure flag */
|
|
}
|
|
|
|
for (j=0; j<ICONHEIGHT; j++) {
|
|
for (i=0; i<ICONWIDTH; i++)
|
|
fscanf(iconfile, "%x", &icon[j][i]);
|
|
}
|
|
fclose(iconfile);
|
|
return(1); /* return a success flag */
|
|
}
|
|
|
|
|
|
void init_graphics(void)
|
|
{
|
|
/* This function initializes the graphics hardware.
|
|
*/
|
|
int gdriver = CGA;
|
|
int gmode, gerror;
|
|
|
|
gmode =4;
|
|
initgraph(&gdriver,&gmode,"");
|
|
if ((gerror = graphresult()) < 0) {
|
|
printf("Failed graphics initialization: gerror=%d\n",
|
|
gerror);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void show_icon(void)
|
|
{
|
|
/* This function displays the icon pattern stored in the
|
|
* icon array.
|
|
*/
|
|
|
|
int x, y;
|
|
|
|
for (y=0; y<ICONHEIGHT; y++)
|
|
for (x=0; x<ICONWIDTH; x++) {
|
|
if (icon[y][x] == 1) {
|
|
putimage(BIGICONLEFT+2*(x*(BIGBITSIZE+NORM_WIDTH))+1,
|
|
BIGICONTOP+y*(BIGBITSIZE+NORM_WIDTH)+1, bigbit,
|
|
XOR_PUT);
|
|
toggle_icons_bit(x, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[LISTING TWO]
|
|
|
|
/* mouse.c -- routines to support a Microsoft compatible mouse.
|
|
* This package assumes that you are running under
|
|
* graphics mode.
|
|
*/
|
|
|
|
#include <dos.h>
|
|
#include <conio.h>
|
|
#include "mouse.h"
|
|
#include "graphics.h"
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
int mouseexists; /* internal variable set true if a */
|
|
/* mouse driver is detected */
|
|
|
|
|
|
void mouse(int *m1, int *m2, int *m3, int *m4)
|
|
{
|
|
/*
|
|
* This function provides the interface between the mouse
|
|
* driver and an application program. Several predefined mouse
|
|
* functions supported by the Microsoft mouse are available.
|
|
* Parameters are passed and returned with the ax, bx, cx and
|
|
* dx registers.
|
|
*/
|
|
union REGS inregs, outregs;
|
|
|
|
inregs.x.ax = *m1;
|
|
inregs.x.bx = *m2;
|
|
inregs.x.cx = *m3;
|
|
inregs.x.dx = *m4;
|
|
int86(0x33, &inregs, &outregs);
|
|
*m1 = outregs.x.ax; /* return parameters */
|
|
*m2 = outregs.x.bx;
|
|
*m3 = outregs.x.cx;
|
|
*m4 = outregs.x.dx;
|
|
}
|
|
|
|
|
|
int initmouse(void)
|
|
{
|
|
/*
|
|
* This function initializes the mouse and displays
|
|
* the mouse cursor at the top, left of the screen, if one
|
|
* is present.
|
|
*/
|
|
int m1, m2, m3, m4, gmode;
|
|
char far *memory = (char far *)0x004000049L;
|
|
|
|
mouseexists = TRUE;
|
|
m1 = RESET_MOUSE;
|
|
mouse(&m1, &m2, &m3, &m4);
|
|
if (m1) { /* if mouse reset okay, assume */
|
|
gmode = getgraphmode(); /* mouse exists */
|
|
if (gmode == HERCMONOHI) { /* Test for Hercules */
|
|
*memory = 0x06;
|
|
}
|
|
m1 = SET_MOUSE_COORD;
|
|
mouse(&m1, &m2, &m3, &m4); /* mouse exists and draw the */
|
|
showmouse(); /* cursor on the screen at 0,0 */
|
|
return(1); /* return a success flag */
|
|
}
|
|
else { /* no mouse installed */
|
|
mouseexists = FALSE;
|
|
return(0); /* return a no-mouse found flag */
|
|
}
|
|
}
|
|
|
|
|
|
void hidemouse(void)
|
|
{
|
|
/* This function removes the mouse cursor from the screen. It
|
|
* should be called before displaying data on the screen.
|
|
* Use showmouse() to redisplay the mouse cursor. The mouse
|
|
* cursor still moves even though it is not visible. Don't
|
|
* call hidemouse() if the mouse is not already visible.
|
|
*/
|
|
int m1, m2, m3, m4;
|
|
|
|
if (mouseexists) { /* check for mouse */
|
|
m1 = HIDE_MOUSE; /* hide the mouse cursor */
|
|
mouse(&m1, &m2, &m3, &m4);
|
|
}
|
|
}
|
|
|
|
|
|
void showmouse(void)
|
|
{
|
|
/* This function displays the mouse cursor. You should not call
|
|
* this function if the mouse is already visible.
|
|
*/
|
|
int m1, m2, m3, m4;
|
|
|
|
if (mouseexists) { /* make sure mouse exists */
|
|
m1 = SHOW_MOUSE;
|
|
mouse(&m1, &m2, &m3, &m4); /* display mouse cursor */
|
|
}
|
|
}
|
|
|
|
|
|
void getmousecoords(int *x, int *y)
|
|
{
|
|
/*
|
|
* This function returns the position of the mouse cursor.
|
|
*/
|
|
int m1, m2;
|
|
|
|
if (mouseexists) {
|
|
m1 = GET_MOUSE_STATUS;
|
|
mouse(&m1, &m2, x, y);
|
|
/* adjust for virtual coordinates */
|
|
if (getmaxx() == 319) (*x) /= 2;
|
|
}
|
|
}
|
|
|
|
|
|
int testbutton(int testtype, int whichbutton)
|
|
{
|
|
/*
|
|
* This function tests a mouse button state. It returns TRUE
|
|
* if the specified mouse button (whichbutton) meets the
|
|
* specified action (as indicated by testtype); otherwise the
|
|
* function returns FALSE.
|
|
*/
|
|
int m1, m2, m3, m4;
|
|
|
|
m1 = testtype;
|
|
if (whichbutton == LEFT_BUTTON || whichbutton ==
|
|
EITHER_BUTTON) {
|
|
m2 = LEFT_BUTTON;
|
|
mouse(&m1, &m2, &m3, &m4);
|
|
if (m2) return(TRUE); /* return TRUE if action ok*/
|
|
}
|
|
if (whichbutton == RIGHT_BUTTON || whichbutton ==
|
|
EITHER_BUTTON) {
|
|
m1 = testtype;
|
|
m2 = RIGHT_BUTTON;
|
|
mouse(&m1, &m2, &m3, &m4);
|
|
if (m2) return(TRUE); /* return TRUE if action ok */
|
|
}
|
|
return(FALSE); /* return FALSE as a catch all */
|
|
}
|
|
|
|
|
|
int waitforinput(int whichbutton)
|
|
{
|
|
/* This function returns a character if a key has been pressed,
|
|
* -1 if a mouse button has been pressed; otherwise a zero. If
|
|
a mouse exists, this routine favors any keyboard action.
|
|
*/
|
|
int c = 0;
|
|
|
|
while (!c) {
|
|
if (kbhit()) /* check if a key has been pressed */
|
|
c =getch(); /* return the character */
|
|
else {
|
|
if (testbutton(CHECK_BUTTON_PRESS, whichbutton)) {
|
|
while (!testbutton(CHECK_BUTTON_RELEASE,
|
|
whichbutton));
|
|
c = -1;
|
|
}
|
|
else if (testbutton(CHECK_BUTTON_RELEASE,
|
|
whichbutton)) {
|
|
c = -1;
|
|
}
|
|
}
|
|
}
|
|
return(c);
|
|
}
|
|
|
|
|
|
[LISTING THREE]
|
|
|
|
|
|
/* mouse.h -- this file includes function prototypes and macro
|
|
* constants for the functions in mouse.c.
|
|
*/
|
|
|
|
/* The following is a list of constants that correspond to the
|
|
* mouse functions supported in mouse.c.
|
|
*/
|
|
|
|
#define RESET_MOUSE 0
|
|
#define SHOW_MOUSE 1
|
|
#define HIDE_MOUSE 2
|
|
#define GET_MOUSE_STATUS 3
|
|
#define SET_MOUSE_COORD 4
|
|
#define CHECK_BUTTON_PRESS 5
|
|
#define CHECK_BUTTON_RELEASE 6
|
|
#define SET_MOUSE_HORIZ_RANGE 7 /* not used */
|
|
#define SET_MOUSE_VERT_RANGE 8 /* not used */
|
|
#define SET_GRAPHICS_CURSOR 9 /* not used */
|
|
#define GET_MOUSE_MOVEMENT 11
|
|
#define SET_MICKEY_RATIO 15 /* not used */
|
|
|
|
#define LEFT_BUTTON 0 /* use left button */
|
|
#define RIGHT_BUTTON 1 /* use right button */
|
|
#define EITHER_BUTTON 2 /* use either button */
|
|
|
|
|
|
/* The function prototypes for the functions in mouse.c
|
|
*/
|
|
|
|
void mouse(int *m1, int *m2, int *m3, int *m4);
|
|
int initmouse(void);
|
|
void getmousecoords(int *x, int *y);
|
|
void hidemouse(void);
|
|
void showmouse(void);
|
|
int testbutton(int testtype, int whichbutton);
|
|
int waitforinput(int whichbutton);
|