_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);