netmapr/netmapr.c

4943 lines
141 KiB
C

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <SDL/SDL.h>
#include <SDL/SDL_keysym.h>
#include "netmapr.h"
#include "constants.h"
SDL_Surface *screen, *buffer;
SDL_Surface *emptyimg;
SDL_Event event;
SDL_Color white = { 255, 255, 255, 0};
SDL_Color black = { 0, 0, 0, 0};
SDL_Color red = { 255, 0, 0, 0};
SDL_Color green = { 0, 255, 0, 0};
SDL_Color blue = { 0, 0, 255, 0};
SDL_Color yellow = { 255, 255, 0, 0};
SDL_Color cyan = { 0, 255, 255, 0};
SDL_Color purple = { 255, 0, 255, 0};
SDL_Color grey = { 90, 90, 90, 0};
SDL_Color grey2 = { 70, 70, 70, 0};
SDL_Color grey3 = { 50, 50, 50, 0};
SDL_Color grey4 = { 30, 30, 30, 0};
SDL_Cursor *normalmouse;
SDL_Cursor *objmouse;
SDL_Cursor *textmouse;
xy_t fillstack[MAXFILLSTACK];
int fillstackptr = 0;
SDL_Color fgcol;
SDL_Color objfillcol;
int modified = FALSE;
int numobjtypes = 0;
int numletters = 0;
int numbuttons = 0;
int nummaps = 1;
int history[MAXHISTORY];
int numhistory = 0;
int children[MAXCHILDREN];
int numchildren = 0;
char currentfilename[BUFLEN];
int state = S_NONE;
SDL_Surface *bg; /* background for temp images*/
int *linebg; /* background for temp lines */
int bgx,bgy;
int bgw,bgh;
int xoff,yoff;
SDL_Rect temparea;
char statustext[BUFLEN];
int curmap = 0;
int startx,starty;
int textanchor;
char text[BUFLEN];
int startobj,endobj;
char progdir[BUFLEN];
int shift;
int main (int argc, char **argv) {
int done;
int c;
int mod;
int o;
Uint32 oldticks = 0;
Uint32 ticks;
int doubleclick = FALSE;
int autoload = FALSE;
if (argc == 2) {
strcpy(text, argv[1]);
autoload = TRUE;
}
if (getenv("NETMAPRDIR") != NULL) {
strncpy(progdir, getenv("NETMAPRDIR"), BUFLEN);
} else {
strcpy(progdir, "/usr/local/share/netmapr");
}
if (initgraphics()) {
printf("Error initialising graphics.\n");
exit(1);
}
atexit(cleanup);
/* TEST */
if (autoload) {
loadmap();
strcpy(text, "");
}
drawscreen();
/* main loop */
done = 0;
while (!done) {
/* check for input */
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
if (isonmap(event.button.x, event.button.y)) {
if (state == S_NONE) {
mod = SDL_GetModState();
if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_CTRL) == 0)) {
/* is there a selected link? if so check for it first */
if ((map[curmap].selecteditemtype == T_LINK) && (map[curmap].selecteditem != -1) &&
(isonlinkdst(map[curmap].selecteditem, event.button.x,event.button.y)) ) {
map[curmap].curlink = map[curmap].selecteditem;
startlinkdstmove(event.button.x, event.button.y);
} else if ((map[curmap].selecteditemtype == T_LINK) && (map[curmap].selecteditem != -1) &&
(isonlinksrc(map[curmap].selecteditem, event.button.x,event.button.y)) ) {
map[curmap].curlink = map[curmap].selecteditem;
startlinksrcmove(event.button.x, event.button.y);
} else if ( ((map[curmap].selecteditemtype == T_LINK) || (map[curmap].selecteditemtype == T_LINKPOINT))
&& (map[curmap].selecteditem != -1) &&
(isonlinkpoint(map[curmap].selecteditem, event.button.x,event.button.y) != -1) ) {
map[curmap].curlink = map[curmap].selecteditem;
map[curmap].curlinkpoint = isonlinkpoint(map[curmap].selecteditem, event.button.x,event.button.y);
startlinkpointmove(event.button.x, event.button.y);
} else {
// move/select object
o = thingat(event.button.x, event.button.y);
if (o != -1) {
switch (map[curmap].thing[o].type) {
case T_OBJECT:
map[curmap].curobj = map[curmap].thing[o].id;
startobjmove(event.button.x,event.button.y);
break;
case T_LINK:
map[curmap].curlink = map[curmap].thing[o].id;
startlinkmove(event.button.x, event.button.y);
break;
case T_TEXT:
map[curmap].curtext = map[curmap].thing[o].id;
starttextmove(event.button.x, event.button.y);
break;
}
}
}
} else if ((event.button.button == SDL_BUTTON_MIDDLE) ||
((event.button.button == SDL_BUTTON_LEFT) && (mod & KMOD_CTRL))) {
// if we're over an object, start drawing a new link
o = objat(event.button.x, event.button.y);
if (o != -1) {
map[curmap].curobj = o;
startlink(event.button.x,event.button.y);
}
} else if (event.button.button == SDL_BUTTON_RIGHT) {
// resize object
o = objat(event.button.x, event.button.y);
if (o != -1) {
map[curmap].curobj = o;
startresize(event.button.x,event.button.y);
} else {
// resize text
o = textat(event.button.x, event.button.y);
if (o != -1) {
map[curmap].curtext = o;
startresizetext(event.button.x,event.button.y);
}
}
} else if (event.button.button == SDL_BUTTON_WHEELUP) {
if (map[curmap].selecteditem != -1) {
/* raise the selected object */
raiseselected();
}
} else if (event.button.button == SDL_BUTTON_WHEELDOWN) {
if (map[curmap].selecteditem != -1) {
/* lower the selected object */
lowerselected();
}
}
}
}
break;
case SDL_MOUSEBUTTONUP:
mod = SDL_GetModState();
if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_CTRL) == 0)) {
ticks = SDL_GetTicks();
if ((ticks - oldticks) <= DOUBLECLICKTHRES) {
doubleclick = TRUE;
} else {
doubleclick = FALSE;
}
oldticks = ticks;
if (isonmap(event.button.x, event.button.y)) {
if (state != S_REALLYQUIT) {
//if ((doubleclick) && (objat(event.button.x, event.button.y) == map[curmap].selecteditem)) {
if (doubleclick) {
o = objat(event.button.x, event.button.y);
/* only works on an object */
//if (map[curmap].selecteditem != -1) {
if (o != -1) {
/* can't create a new child via double click */
if (map[curmap].obj[o].child != -1) {
changestate(S_NONE);
drillto(map[curmap].obj[o].child);
} else {
sprintf(statustext, "Cannot drill down - object has no children (use drill tool to create one).");
map[curmap].selecteditem = -1;
changestate(S_NONE);
drawmap();
}
}
}
}
if (state == S_NONE) {
if (map[curmap].selecteditem != -1) {
map[curmap].selecteditem = -1;
map[curmap].selecteditemtype = T_EMPTY;
sprintf(statustext,"Objects/lines deselected.\n");
drawmap();
}
} else if (state == S_REALLYQUIT) {
o = getyn(event.button.x, event.button.y);
if (o == YES) {
done = TRUE;
} else {
changestate(S_NONE);
drawmap();
}
} else if (state == S_MATCHSIZE) {
o = objat(event.button.x, event.button.y);
if (o == -1) {
changestate(S_NONE);
sprintf(statustext, "Size match mode aborted.");
drawstatusbar();
} else {
int n;
/* resize selected item to match one which was clicked */
map[curmap].obj[map[curmap].selecteditem].w = map[curmap].obj[o].w;
map[curmap].obj[map[curmap].selecteditem].h = map[curmap].obj[o].h;
/* adjust offsets on all links to/from object */
for (n = 0; n < map[curmap].numlinks; n++) {
if (map[curmap].olink[n].srcobj == map[curmap].selecteditem) {
map[curmap].olink[n].srcxoff = (map[curmap].obj[o].w / 2);
map[curmap].olink[n].srcyoff = (map[curmap].obj[o].h / 2);
}
if (map[curmap].olink[n].dstobj == map[curmap].selecteditem) {
map[curmap].olink[n].dstxoff = (map[curmap].obj[o].w / 2);
map[curmap].olink[n].dstyoff = (map[curmap].obj[o].h / 2);
}
}
changestate(S_NONE);
sprintf(statustext, "Object #%d resized to match object #%d.",map[curmap].selecteditem,o);
drawmap();
}
} else if (state == S_MATCHX) {
o = objat(event.button.x, event.button.y);
if (o == -1) {
changestate(S_NONE);
sprintf(statustext, "X position match mode aborted.");
drawstatusbar();
} else {
/* move selected item to match one which was clicked */
/* match middle of objects! */
map[curmap].obj[map[curmap].selecteditem].x =
(map[curmap].obj[o].x + (map[curmap].obj[o].w/2))
-
(map[curmap].obj[map[curmap].selecteditem].w/2);
changestate(S_NONE);
sprintf(statustext, "Object #%d X relocated to match object #%d.",map[curmap].selecteditem,o);
drawmap();
}
} else if (state == S_MATCHY) {
o = objat(event.button.x, event.button.y);
if (o == -1) {
changestate(S_NONE);
sprintf(statustext, "Y position match mode aborted.");
drawstatusbar();
} else {
/* move selected item to match one which was clicked */
map[curmap].obj[map[curmap].selecteditem].y =
(map[curmap].obj[o].y + (map[curmap].obj[o].h / 2))
-
map[curmap].obj[map[curmap].selecteditem].h/2;
changestate(S_NONE);
sprintf(statustext, "Object #%d Y relocated to match object #%d.",map[curmap].selecteditem,o);
drawmap();
}
} else if (state == S_OBJMOVING) {
/* has mouse actually moved? */
if ((event.button.x == startx) && (event.button.y == starty)) {
/* select the object */
map[curmap].selecteditem = map[curmap].curobj;
map[curmap].selecteditemtype = T_OBJECT;
changestate(S_NONE);
sprintf(statustext, "Object #%d (%s) selected.\n",map[curmap].selecteditem, objtype[map[curmap].obj[map[curmap].selecteditem].type].name);
drawmap();
} else {
// actually move the object
if (!endobjmove(event.button.x, event.button.y)) {
sprintf(statustext, "Object #%d moved to (%d,%d).\n",map[curmap].curobj,event.button.x, event.button.y);
}
changestate(S_NONE);
drawmap();
}
} else if (state == S_LINKMOVING) {
/* has mouse actually moved? */
if ((event.button.x == startx) && (event.button.y == starty)) {
/* select the link */
map[curmap].selecteditem = map[curmap].curlink;
map[curmap].selecteditemtype = T_LINK;
changestate(S_NONE);
sprintf(statustext,"Link #%d selected.\n",map[curmap].selecteditem);
drawmap();
} else {
// actually move the link
endlinkmove(event.button.x, event.button.y);
changestate(S_NONE);
sprintf(statustext,"Link #%d moved to (%d,%d).\n",map[curmap].curlink,event.button.x, event.button.y);
drawmap();
}
} else if (state == S_LINKPOINTMOVE) {
/* has mouse actually moved? */
if ((event.button.x == startx) && (event.button.y == starty)) {
/* select the link point */
map[curmap].selecteditem = map[curmap].curlink;
map[curmap].selecteditemtype = T_LINKPOINT;
map[curmap].selectedlinkpoint = map[curmap].curlinkpoint;
changestate(S_NONE);
sprintf(statustext,"Link #%d point #%d selected.\n",map[curmap].selecteditem,map[curmap].selectedlinkpoint);
drawmap();
} else {
// actually move the link
endlinkpointmove(event.button.x, event.button.y);
changestate(S_NONE);
sprintf(statustext,"Link #%d moved to (%d,%d).\n",map[curmap].curlink,event.button.x, event.button.y);
drawmap();
}
} else if (state == S_TEXTMOVING) {
/* has mouse actually moved? */
if ((event.button.x == startx) && (event.button.y == starty)) {
/* select the object */
map[curmap].selecteditem = map[curmap].curtext;
map[curmap].selecteditemtype = T_TEXT;
changestate(S_NONE);
sprintf(statustext,"Text item #%d selected.\n",map[curmap].selecteditem);
drawmap();
} else {
// actually move the text
if (!endtextmove(event.button.x, event.button.y)) {
sprintf(statustext,"Text item #%d moved to (%d,%d).\n",map[curmap].curtext,event.button.x, event.button.y);
}
changestate(S_NONE);
drawmap();
}
} else if (state == S_LINKSRCMOVE) {
// actually move the link src endpoint
endlinksrcmove(event.button.x, event.button.y);
changestate(S_NONE);
drawmap();
} else if (state == S_LINKDSTMOVE) {
// actually move the link dst endpoint
endlinkdstmove(event.button.x, event.button.y);
changestate(S_NONE);
drawmap();
} else if (state == S_ADDOBJ) {
/* create a new object */
createobject(map[curmap].selectedtype, event.button.x, event.button.y);
drawmap();
changestate(S_NONE);
} else if (state == S_ADDTEXT) {
/* start listening for text input */
startx = event.button.x;
starty = event.button.y;
textanchor = objat(event.button.x,event.button.y);
if (textanchor != -1) {
startx = map[curmap].obj[textanchor].x;
starty = map[curmap].obj[textanchor].y + map[curmap].obj[textanchor].h+3;
}
strcpy(text, "");
bg = NULL;
updatetextcursor();
changestate(S_TYPETEXT);
} else if (state == S_FGCOL) {
getcolor(screen, event.button.x, event.button.y, &fgcol);
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_LINK) {
map[curmap].olink[map[curmap].selecteditem].col = fgcol;
sprintf(statustext, "Colour of link #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b);
} else if (map[curmap].selecteditemtype == T_TEXT) {
map[curmap].textob[map[curmap].selecteditem].c = fgcol;
sprintf(statustext, "Colour of text item #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b);
} else {
sprintf(statustext, "Foreground colour selected: R=%d,G=%d,B=%d",fgcol.r,fgcol.g,fgcol.b);
}
} else {
sprintf(statustext, "Foreground colour selected: R=%d,G=%d,B=%d",fgcol.r,fgcol.g,fgcol.b);
}
changestate(S_NONE);
drawmap();
} else if (state == S_CREATETELE) {
int pos;
if (event.button.y >= 50) {
pos = (event.button.y - 50) / (DEFTEXTH*2);
pos--;
if (pos == -1) {
map[curmap].obj[map[curmap].selecteditem].child = pos;
sprintf(statustext, "Map link removed.");
changestate(S_NONE);
drawmap();
} else if (pos <= (nummaps-1)) {
if ((map[curmap].selecteditem != -1) && (map[curmap].selecteditemtype == T_OBJECT)) {
if (pos != curmap) {
map[curmap].obj[map[curmap].selecteditem].child = pos;
sprintf(statustext, "Map link created.");
changestate(S_NONE);
drawmap();
} else {
sprintf(statustext, "ERROR: Cannot link to current map!");
drawstatusbar();
}
}
} else { /* mouse is not over a map name */
sprintf(statustext, "Map link creation cancelled.");
changestate(S_NONE);
drawmap();
}
} else {
sprintf(statustext, "Map link creation cancelled.");
changestate(S_NONE);
drawmap();
}
}
} else if (isonobox(event.button.x, event.button.y)) {
int tempx,tempy;
tempx = (event.button.x - obox.x) / obox.gridsize;
tempy = (event.button.y - obox.y) / obox.gridsize;
map[curmap].selectedtype = tempy*obox.gridrowlen + tempx + (obox.pos*3);
if (map[curmap].selectedtype >= numobjtypes) map[curmap].selectedtype = numobjtypes-1;
sprintf(statustext,"Object type '%s' selected.\n",objtype[map[curmap].selectedtype].name);
drawstatusbar();
drawobox();
} else if (isongoback(event.button.x, event.button.y)) {
/* go back */
goback();
} else if (isonmapname(event.button.x, event.button.y)) {
/* rename current map */
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, map[curmap].name);
changestate(S_MAPNAMING);
drawmap();
break;
} else if (isonmapboxchildren(event.button.x, event.button.y)) {
int pos;
/* change to child */
pos = (event.button.y - (mapbox.y+(DEFTEXTH*2)+2)) / DEFTEXTH;
if (pos >= numchildren) {
sprintf(statustext, "ERROR: Invalid child map %d (max is %d).",pos,numchildren);
drawstatusbar();
} else {
drillto(children[pos]);
}
break;
} else if (isontoolbox(event.button.x, event.button.y)) {
int tempx,tempy, selection;
tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3);
tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3);
selection = tempy*toolbox.gridrowlen + tempx;
switch (selection) {
case TB_POINTER:
/* special case - update sbar */
sprintf(statustext, "Selection mode entered.");
drawstatusbar();
changestate(S_NONE);
map[curmap].curobj = -1;
break;
case TB_ADDOBJ:
changestate(S_ADDOBJ);
if (map[curmap].selectedtype < 0) map[curmap].selectedtype = 0;
break;
case TB_ADDTEXT:
changestate(S_ADDTEXT);
break;
case TB_NEW:
initvars();
changestate(S_NONE);
drawmap();
break;
case TB_MATCHSIZE:
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHSIZE);
drawmap();
}
}
break;
case TB_MATCHX:
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHX);
drawmap();
}
}
break;
case TB_MATCHY:
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHY);
drawmap();
}
}
break;
case TB_FGCOL:
changestate(S_FGCOL);
drawmap();
break;
case TB_FILLCOL:
sprintf(statustext, "Select Fill Colour feature not yet implemented.");
drawstatusbar();
break;
case TB_LINESTYLE:
sprintf(statustext, "Select Line Style feature not yet implemented.");
drawstatusbar();
break;
case TB_DELETEMAP:
sprintf(statustext, "Delete Current Map feature not yet implemented.");
drawstatusbar();
break;
case TB_CREATETELE:
if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) {
changestate(S_CREATETELE);
drawmap();
} else {
sprintf(statustext,"Cannot create map link - no object selected!");
drawstatusbar();
}
break;
case TB_DRILLDOWN:
if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) {
drillto(map[curmap].obj[map[curmap].selecteditem].child);
} else {
sprintf(statustext,"Cannot drill down - no object selected!");
drawstatusbar();
}
break;
case TB_SAVE:
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, currentfilename);
changestate(S_SAVING);
drawmap();
break;
case TB_LOAD:
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, currentfilename);
changestate(S_LOADING);
drawmap();
break;
}
drawtoolbox();
} /* end if is on map */
} else if ((event.button.button == SDL_BUTTON_MIDDLE) ||
((event.button.button == SDL_BUTTON_LEFT) && (mod & KMOD_CTRL))) {
if (state == S_DRAWLINK) {
// finish drawing link
o = objat(event.button.x, event.button.y);
if ((o != -1) && (o != startobj)) {
endobj = o;
endlink(event.button.x,event.button.y);
changestate(S_NONE);
drawmap();
} else {
pasteline(screen,linebg);
sprintf(statustext,"Aborting link #%d.\n", map[curmap].numlinks);
drawstatusbar();
}
changestate(S_NONE);
} else if (state == S_NONE) {
/* are we on a link? if so, add a point to it */
o = linkat(event.button.x, event.button.y);
if (o != -1) {
addlinkpoint(o, event.button.x, event.button.y);
/* select the link */
map[curmap].selecteditemtype = T_LINK;
map[curmap].selecteditem = o;
drawmap();
}
}
} else if (event.button.button == SDL_BUTTON_RIGHT) {
if (state == S_RESIZING) {
// end resize
endresize(event.button.x, event.button.y);
changestate(S_NONE);
} else if (state == S_TEXTRESIZING) {
// end text resize
endtextresize(event.button.x, event.button.y);
changestate(S_NONE);
}
}
break;
case SDL_MOUSEMOTION:
switch (state) {
case S_OBJMOVING:
updatemoveshadow(event.button.x, event.button.y);
break;
case S_RESIZING:
updateresizeshadow(event.button.x, event.button.y);
break;
case S_DRAWLINK:
updatelinkshadow(event.button.x, event.button.y);
break;
case S_TEXTMOVING:
updatetextshadow(event.button.x, event.button.y);
break;
case S_TEXTRESIZING:
updateresizetextshadow(event.button.x, event.button.y);
break;
case S_LINKPOINTMOVE:
updatelinkpointshadow(event.button.x, event.button.y);
break;
}
break;
case SDL_QUIT:
if (modified) {
strcpy(text, "Changes not saved - really quit?");
changestate(S_REALLYQUIT);
drawmap();
} else {
done = TRUE;
}
break;
case SDL_VIDEOEXPOSE:
/* redraw screen */
drawscreen();
break;
case SDL_KEYDOWN:
c = event.key.keysym.sym;
mod = SDL_GetModState();
/* state independant */
if (mod & KMOD_SHIFT) {
if ((c >= 'a') && (c <= 'z')) {
c -= 32;
} else if (c == '1') {
c = '!';
} else if (c == '2') {
c = '@';
} else if (c == '3') {
c = '#';
} else if (c == '4') {
c = '$';
} else if (c == '5') {
c = '%';
} else if (c == '6') {
c = '^';
} else if (c == '7') {
c = '&';
} else if (c == '8') {
c = '*';
} else if (c == '9') {
c = '(';
} else if (c == '0') {
c = ')';
} else if (c == '-') {
c = '_';
} else if (c == '=') {
c = '+';
} else if (c == '\\') {
c = '|';
} else if (c == ';') {
c = ':';
} else if (c == '\'') {
c = '"';
} else if (c == ',') {
c = '<';
} else if (c == '.') {
c = '>';
} else if (c == '/') {
c = '?';
}
}
/* state dependant */
if ((state == S_TYPETEXT) || (state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING)) {
if ((c >= FIRSTLET) && (c <= LASTLET)) {
char temptext[2];
sprintf(temptext, "%c", c);
strcat(text, temptext);
updatetextcursor();
} else if (c == SDLK_ESCAPE) {
sprintf(statustext, "Aborted.");
changestate(S_NONE);
drawmap();
} else if (c == ' ') {
strcat(text, " ");
updatetextcursor();
} else if (c == SDLK_BACKSPACE) {
text[strlen(text)-1] = '\0';
updatetextcursor();
} else if (c == 13) { /* enter */
if (state == S_TYPETEXT) {
endtext();
} else if (state == S_SAVING) {
savemap();
changestate(S_NONE);
drawmap();
} else if (state == S_LOADING) {
loadmap();
changestate(S_NONE);
drawmap();
} else if (state == S_MAPNAMING) {
/* rename map */
strcpy(map[curmap].name,text);
changestate(S_NONE);
sprintf(statustext, "Map #%d renamed to '%s'.",curmap,map[curmap].name);
drawmap();
}
}
} else {
if (c == 'a') { /* add map[curmap].object */
if (state == S_NONE) {
changestate(S_ADDOBJ);
}
}
if (c == 't') { /* add text */
if (state == S_NONE) {
changestate(S_ADDTEXT);
}
}
if (c == 's') { /* save */
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, currentfilename);
changestate(S_SAVING);
drawmap();
}
if ((c == 'l') || (c == 'o')) { /* load, open */
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, currentfilename);
changestate(S_LOADING);
drawmap();
}
if ((c == ',') || (c == 'q')) { /* scroll object box up */
if (obox.pos > 0) {
obox.pos--;
drawobox();
}
}
if ((c == '.') || (c == 'w')) { /* scroll object box down */
int fitx,fity,fit;
/* figure out how many objects we can fit in the box */
fitx = (obox.width / obox.gridsize);
fity = ((obox.height+3) / obox.gridsize);
fit = fitx * fity;
/* check if incrementing position is okay or not */
if (((obox.pos+1)*3 + fit) <= (numobjtypes+2)) {
obox.pos++;
drawobox();
}
}
if (c == 'x') {
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHX);
drawmap();
}
}
}
if (c == 'y') {
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHY);
drawmap();
}
}
}
if (c == 'b') {
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
changestate(S_MATCHSIZE);
drawmap();
}
}
}
if (c == 'd') { /* drill down */
if (state == S_NONE) {
if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) {
drillto(map[curmap].obj[map[curmap].selecteditem].child);
} else {
sprintf(statustext,"Cannot drill down - no object selected!");
drawstatusbar();
}
} else {
sprintf(statustext,"Cannot drill down in state %d.",state);
drawstatusbar();
}
}
if (c == SDLK_BACKSPACE) {
goback();
}
if (c == SDLK_DELETE) {
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_LINKPOINT) {
int i;
for (i = map[curmap].selectedlinkpoint; i < (map[curmap].olink[map[curmap].selecteditem].npoints-1); i++) {
map[curmap].olink[map[curmap].selecteditem].point[i].x = map[curmap].olink[map[curmap].selecteditem].point[i+1].x;
map[curmap].olink[map[curmap].selecteditem].point[i].y = map[curmap].olink[map[curmap].selecteditem].point[i+1].y;
}
map[curmap].olink[map[curmap].selecteditem].npoints--;
/* move selection to next point on same line */
if (map[curmap].olink[map[curmap].selecteditem].npoints > 0) {
if (map[curmap].selectedlinkpoint >= map[curmap].olink[map[curmap].selecteditem].npoints) {
map[curmap].selectedlinkpoint = map[curmap].olink[map[curmap].selecteditem].npoints-1;
}
} else {
/* deselect point (leave link selected) */
map[curmap].selectedlinkpoint = -1;
map[curmap].selecteditemtype = T_LINK;
}
sprintf(statustext, "Deleted link #%d point #%d.",map[curmap].selecteditem,map[curmap].selectedlinkpoint);
drawmap();
} else {
deletething(map[curmap].selecteditem,map[curmap].selecteditemtype);
}
}
}
if (c == ']') { /* raise */
if (map[curmap].selecteditem != -1) {
/* raise the selected map[curmap].object */
raiseselected();
}
}
if (c == '[') { /* lower */
if (map[curmap].selecteditem != -1) {
/* lower the selected map[curmap].object */
lowerselected();
}
}
}
break;
}
}
} /* end main loop */
return 0;
}
void addlinkpoint(int linkid, int x, int y) {
int pos;
int i;
pos = findpointpos(&map[curmap].olink[linkid],x,y);
map[curmap].olink[linkid].npoints++;
/* shuffle points from that point upwards */
for (i = (map[curmap].olink[linkid].npoints-1);i > pos ; i--) {
map[curmap].olink[linkid].point[i] = map[curmap].olink[linkid].point[i-1];
}
map[curmap].olink[linkid].point[pos].x = x;
map[curmap].olink[linkid].point[pos].y = y;
modified = TRUE;
sprintf(statustext, "Point added to link #%d",linkid);
}
int addvector(vectorimg_t *vimg, int type, int x1, int y1, int x2, int y2, SDL_Color *c) {
if ((vimg->vnum + 1) >= MAXVECTORSPERIMAGE) return TRUE;
vimg->vector[vimg->vnum].type = type;
vimg->vector[vimg->vnum].x1 = x1;
vimg->vector[vimg->vnum].y1 = y1;
vimg->vector[vimg->vnum].x2 = x2;
vimg->vector[vimg->vnum].y2 = y2;
vimg->vector[vimg->vnum].c.r = c->r;
vimg->vector[vimg->vnum].c.g = c->g;
vimg->vector[vimg->vnum].c.b = c->b;
vimg->vnum = vimg->vnum + 1;
return FALSE;
}
void changestate(int newstate) {
if (newstate != state) {
if ((state == S_ADDOBJ) || (state == S_ADDTEXT)) {
/* change mouse back to normal */
SDL_SetCursor(normalmouse);
}
if (newstate == S_ADDOBJ) SDL_SetCursor(objmouse);
if (newstate == S_ADDTEXT) SDL_SetCursor(textmouse);
state = newstate;
drawtoolbox();
switch (state) {
case S_NONE:
//sprintf(statustext,"Selection mode enabled.\n"); fflush(stdout);
break;
case S_ADDOBJ:
sprintf(statustext,"Object creation mode enabled.\n"); fflush(stdout);
break;
case S_ADDTEXT:
sprintf(statustext,"Text creation mode entered.\n"); fflush(stdout);
break;
case S_TYPETEXT:
sprintf(statustext,"Text entry mode entered.\n"); fflush(stdout);
break;
case S_MATCHSIZE:
sprintf(statustext,"Size-matching mode entered - select object to copy size from...\n"); fflush(stdout);
break;
case S_MATCHX:
sprintf(statustext,"X-matching mode entered - select object to align with...\n"); fflush(stdout);
break;
case S_MATCHY:
sprintf(statustext,"Y-matching mode entered - select object to align with...\n"); fflush(stdout);
break;
case S_MAPNAMING:
sprintf(statustext,"Map rename mode entered.\n"); fflush(stdout);
break;
case S_SAVING:
sprintf(statustext,"Save mode entered.\n"); fflush(stdout);
break;
case S_LOADING:
sprintf(statustext,"Load mode entered.\n"); fflush(stdout);
break;
}
drawstatusbar();
}
}
void cleanup(void) {
SDL_FreeCursor(textmouse);
SDL_FreeCursor(objmouse);
SDL_Quit();
}
int createobject(int type, int x, int y) {
map[curmap].obj[map[curmap].numobjects].type = type;
map[curmap].obj[map[curmap].numobjects].w = objtype[type].defw;
map[curmap].obj[map[curmap].numobjects].h = objtype[type].defh;
if ((x + map[curmap].obj[map[curmap].numobjects].w) >= map[curmap].width) {
x = map[curmap].width - map[curmap].obj[map[curmap].numobjects].w - 1;
}
if ((y + map[curmap].obj[map[curmap].numobjects].h) >= map[curmap].height) {
y = map[curmap].height - map[curmap].obj[map[curmap].numobjects].h - 1;
}
map[curmap].obj[map[curmap].numobjects].x = x;
map[curmap].obj[map[curmap].numobjects].y = y;
map[curmap].obj[map[curmap].numobjects].child = -1;
modified = TRUE;
sprintf(statustext,"Object #%d (%s) created at (%d,%d).\n",map[curmap].numobjects, objtype[type].name, x, y);
drawstatusbar();
/* add to 'thing' list */
map[curmap].thing[map[curmap].numthings].type = T_OBJECT;
map[curmap].thing[map[curmap].numthings].id = map[curmap].numobjects;
map[curmap].numobjects++;
map[curmap].numthings++;
return 0;
}
void copyline(SDL_Surface *screen,int x1, int y1, int x2, int y2, int *lbuf) {
int deltax, deltay;
int numpixels;
int d;
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
int i;
int x;
int y;
SDL_Color bgcol;
/* store coords */
lbuf[0] = x1;
lbuf[1] = y1;
lbuf[2] = x2;
lbuf[3] = y2;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
numpixels = deltax + 1;
d = (deltay*2) - deltax;
dinc1 = deltay << 1;
dinc2 = (deltay-deltax) << 1;
xinc1 = 1;
xinc2 = 1;
yinc1 = 0;
yinc2 = 1;
} else {
numpixels = deltay + 1;
d = (deltax*2) - deltay;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
xinc1 = 0;
xinc2 = 1;
yinc1 = 1;
yinc2 = 1;
}
if (x1 > x2) {
xinc1 = - xinc1;
xinc2 = - xinc2;
}
if (y1 > y2) {
yinc1 = - yinc1;
yinc2 = - yinc2;
}
x = x1; y = y1;
for (i = 0; i < numpixels; i++) {
getcolor(screen, x, y, &bgcol);
lbuf[i+4] = SDL_MapRGB(screen->format, bgcol.r, bgcol.g, bgcol.b);
if (d < 0) {
d += dinc1;
x += xinc1;
y += yinc1;
} else {
d += dinc2;
x += xinc2;
y += yinc2;
}
}
}
void deletething(int id, int type) {
int i;
int found;
if (type == T_LINK) {
/* remove the link*/
deletelink(id);
} else if (type == T_TEXT) {
deletetext(id);
} else if (type == T_OBJECT) {
/* remove any links connecting to this map[curmap].object */
found = 0;
while (found >= 0 ) {
found = -1;
for (i = 0; i < map[curmap].numlinks; i++) {
if ((map[curmap].olink[i].srcobj == id) || (map[curmap].olink[i].dstobj == id)) {
found = i;
break;
}
}
if (found >= 0) {
deletelink(found);
}
}
/* remove any text anchored to this map[curmap].object */
found = 0;
while (found >= 0 ) {
found = -1;
for (i = 0; i < map[curmap].numtext; i++) {
if (map[curmap].textob[i].anchor == id) {
found = i;
break;
}
}
if (found >= 0) {
deletetext(found);
}
}
/* remove the map[curmap].object */
deleteobject(id);
/* shuffle ids on any link referencing this object */
for (i = 0; i < map[curmap].numlinks; i++) {
if (map[curmap].olink[i].srcobj > id) {
map[curmap].olink[i].srcobj--;
}
if (map[curmap].olink[i].dstobj > id) {
map[curmap].olink[i].dstobj--;
}
}
/* shuffle ids on any text referencing this object */
for (i = 0; i < map[curmap].numtext; i++) {
if (map[curmap].textob[i].anchor > id) {
map[curmap].textob[i].anchor--;
}
}
}
modified = TRUE;
map[curmap].selecteditem = -1;
map[curmap].selecteditemtype = -1;
drawmap();
}
void deletelink(int linkid) {
int i;
int n;
int found;
for (i = linkid; i < (map[curmap].numlinks-1); i++) {
map[curmap].olink[i] = map[curmap].olink[i+1];
}
map[curmap].numlinks--;
/* shuffle thing # */
for (n = 0; n < map[curmap].numthings; n++) {
/* mark for deletion */
if ((map[curmap].thing[n].id == linkid) && (map[curmap].thing[n].type == T_LINK)) {
map[curmap].thing[n].id = -1;
}
/* shuffle id */
if ((map[curmap].thing[n].id > linkid) && (map[curmap].thing[n].type == T_LINK)) {
map[curmap].thing[n].id--;
}
}
found = -1;
for (n = 0; n < map[curmap].numthings; n++) {
if ((map[curmap].thing[n].type == T_LINK) && (map[curmap].thing[n].id == -1)) {
found = n;
}
}
if (found != -1) {
// remove the thing
for (n = found; n < (map[curmap].numthings-1); n++) {
map[curmap].thing[n] = map[curmap].thing[n+1];
}
map[curmap].numthings--;
} else {
sprintf(statustext,"Can't find matching thing for link #%d!\n",linkid);
}
modified = TRUE;
sprintf(statustext,"Deleted link #%d.\n",linkid);
drawstatusbar();
}
void deleteobject(int oid) {
int i;
int n;
int found;
for (i = oid; i < (map[curmap].numobjects-1); i++) {
map[curmap].obj[i] = map[curmap].obj[i+1];
}
map[curmap].numobjects--;
/* shuffle thing # */
for (n = 0; n < map[curmap].numthings; n++) {
if ((map[curmap].thing[n].id == oid) && (map[curmap].thing[n].type == T_OBJECT)) {
map[curmap].thing[n].id = -1;
}
if ((map[curmap].thing[n].id > oid) && (map[curmap].thing[n].type == T_OBJECT)) {
map[curmap].thing[n].id--;
}
}
found = -1;
for (n = 0; n < map[curmap].numthings; n++) {
if ((map[curmap].thing[n].type == T_OBJECT) && (map[curmap].thing[n].id == -1 )) {
found = n;
}
}
if (found != -1) {
// remove the thing
for (n = found; n < (map[curmap].numthings-1); n++) {
map[curmap].thing[n] = map[curmap].thing[n+1];
}
map[curmap].numthings--;
} else {
sprintf(statustext,"Can't find matching thing for object #%d!\n",oid);
}
modified = TRUE;
sprintf(statustext,"Deleted object #%d.\n",oid);
drawstatusbar();
}
void deletetext(int textid) {
int i;
int n;
int found;
for (i = textid; i < (map[curmap].numtext-1); i++) {
map[curmap].textob[i] = map[curmap].textob[i+1];
}
map[curmap].numtext--;
/* shuffle thing # */
for (n = 0; n < map[curmap].numthings; n++) {
/* mark for deletion */
if ((map[curmap].thing[n].id == textid) && (map[curmap].thing[n].type == T_TEXT)) {
map[curmap].thing[n].id = -1;
}
/* shuffle id */
if ((map[curmap].thing[n].id > textid) && (map[curmap].thing[n].type == T_TEXT)) {
map[curmap].thing[n].id--;
}
}
found = -1;
for (n = 0; n < map[curmap].numthings; n++) {
if ((map[curmap].thing[n].type == T_TEXT) && (map[curmap].thing[n].id == -1)) {
found = n;
}
}
if (found != -1) {
// remove the thing
for (n = found; n < (map[curmap].numthings-1); n++) {
map[curmap].thing[n] = map[curmap].thing[n+1];
}
map[curmap].numthings--;
} else {
sprintf(statustext,"Can't find matching thing for text item #%d!\n",textid);
}
modified = TRUE;
sprintf(statustext,"Deleted text item #%d.\n",textid);
drawstatusbar();
}
void drawbox(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c) {
drawline(screen,x1,y1,x2,y1,c);
drawline(screen,x1,y1,x1,y2,c);
drawline(screen,x1,y2,x2,y2,c);
drawline(screen,x2,y1,x2,y2,c);
}
void drawcolorchart(SDL_Surface *dest) {
int x,y;
int i;
SDL_Color c;
int speed;
int finished = FALSE;
int size = 18;
c.r = 0;
c.g = 0;
c.b = 0;
speed = 24 ;
for (y = 0; (y < (map[curmap].height-size)) && (!finished); y+= size) {
for (x = 0; (x < (map[curmap].width-size)) && (!finished); x+= size) {
drawbox(dest,x,y,x+(size-1),y+(size-1),black);
/* fill box */
for (i = 1; i <= (size-2); i++) {
drawline(dest, x+1, y+i, x+(size-2), y+i, c);
}
/* change color */
if (c.b + speed > 255) {
c.b = 0;
if (c.g + speed > 255) {
c.g = 0;
if (c.r + speed > 255) {
finished = TRUE;
} else c.r += speed;
} else c.g += speed;
} else c.b += speed;
if (c.r >= 240) c.r = 255;
if (c.g >= 240) c.g = 255;
if (c.b >= 240) c.b = 255;
}
}
SDL_Flip(screen);
}
int drawletter(SDL_Surface *dest,int x, int y, int w, int h, char let, SDL_Color col) {
if ((let < FIRSTLET) || (let > LASTLET)) {
return TRUE;
}
drawvector(dest, &letter[let-FIRSTLET].vect, x, y, w,h, &col);
return FALSE;
}
int findpointpos(link_t *l, int px, int py) {
int i;
int x,y,x2,y2;
int pos = 0;
x = map[curmap].obj[l->srcobj].x + l->srcxoff;
y = map[curmap].obj[l->srcobj].y + l->srcyoff;
for (i = 0; i < l->npoints; i++) {
x2 = l->point[i].x;
y2 = l->point[i].y;
if (isonline(px, py, x, y, x2, y2)) {
return pos;
}
pos++;
x = x2;
y = y2;
}
/* draw line to final map[curmap].object */
x2 = map[curmap].obj[l->dstobj].x + l->dstxoff;
y2 = map[curmap].obj[l->dstobj].y + l->dstyoff;
return pos;
}
void drawline(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c) {
int deltax, deltay;
int numpixels;
int d;
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
int i;
int x;
int y;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
numpixels = deltax + 1;
d = (deltay*2) - deltax;
dinc1 = deltay << 1;
dinc2 = (deltay-deltax) << 1;
xinc1 = 1;
xinc2 = 1;
yinc1 = 0;
yinc2 = 1;
} else {
numpixels = deltay + 1;
d = (deltax*2) - deltay;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
xinc1 = 0;
xinc2 = 1;
yinc1 = 1;
yinc2 = 1;
}
if (x1 > x2) {
xinc1 = - xinc1;
xinc2 = - xinc2;
}
if (y1 > y2) {
yinc1 = - yinc1;
yinc2 = - yinc2;
}
x = x1; y = y1;
for (i = 0; i < numpixels; i++) {
drawpixel(screen,x,y,c);
if (d < 0) {
d += dinc1;
x += xinc1;
y += yinc1;
} else {
d += dinc2;
x += xinc2;
y += yinc2;
}
}
}
void drawlink(SDL_Surface *dest, link_t *l) {
int i;
int x,y,x2,y2;
x = map[curmap].obj[l->srcobj].x + l->srcxoff;
y = map[curmap].obj[l->srcobj].y + l->srcyoff;
for (i = 0; i < l->npoints; i++) {
x2 = l->point[i].x;
y2 = l->point[i].y;
drawline(dest, x,y,x2,y2, l->col);
x = x2;
y = y2;
}
/* draw line to final map[curmap].object */
x2 = map[curmap].obj[l->dstobj].x + l->dstxoff;
y2 = map[curmap].obj[l->dstobj].y + l->dstyoff;
drawline(dest, x,y,x2,y2, l->col);
}
void drawobject(SDL_Surface *dest, mapobject_t *o) {
SDL_Surface *temps;
SDL_Rect area;
Uint32 bgcol;
/* create temp surface */
temps = SDL_CreateRGBSurface(SDL_SWSURFACE,(o->w + 3), (o->h + 3),
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
if (temps == NULL) {
printf("temp surface is NULL!\n");
fflush(stdout);
exit(1);
}
bgcol = SDL_MapRGB(temps->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b);
SDL_FillRect(temps, NULL, bgcol);
/* draw onto temp surface */
drawvector(temps, &objtype[o->type].vimg, 0, 0, o->w, o->h, NULL);
/* set transparent colour on temp surface */
SDL_SetColorKey(temps, SDL_SRCCOLORKEY|SDL_RLEACCEL, bgcol);
/* blit to screen */
/*printf("set area params: x=%d,y=%d w=%d,h=%d x2=%d,y2=%d\n",
o->x, o->y,o->w,o->h,o->x+o->w,o->y+o->h); fflush(stdout);
*/
area.x = o->x;
area.y = o->y;
area.w = o->w;
area.h = o->h;
SDL_BlitSurface(temps, 0, dest, &area);
}
void drawpixel(SDL_Surface *screen, int x, int y, SDL_Color c) {
Uint32 color = SDL_MapRGB(screen->format, c.r, c.g, c.b);
/*if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
return;
}
}*/
switch (screen->format->BytesPerPixel) {
case 1: { /* Assuming 8-bpp */
Uint8 *bufp;
bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
*bufp = color;
}
break;
case 2: { /* Probably 15-bpp or 16-bpp */
Uint16 *bufp;
bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
*bufp = color;
}
break;
case 3: { /* Slow 24-bpp mode, usually not used */
Uint8 *bufp;
bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3;
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
bufp[0] = color;
bufp[1] = color >> 8;
bufp[2] = color >> 16;
} else {
bufp[2] = color;
bufp[1] = color >> 8;
bufp[0] = color >> 16;
}
}
break;
case 4: { /* Probably 32-bpp */
Uint32 *bufp;
bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
*bufp = color;
}
break;
}
/*
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
*/
//SDL_UpdateRect(screen, x, y, 1, 1);
}
void drawmap(void) {
int i;
int testing = 0;
SDL_Rect area;
Uint32 fillcol;
int txoff,tyoff;
int anchoreditem;
if ((state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING)) {
/* show file dialog */
showfiledialog();
return;
}
if (state == S_FGCOL) {
drawcolorchart(screen);
return;
}
if (state == S_CREATETELE) {
drawmaplist(screen);
return;
}
if (state == S_REALLYQUIT) {
drawyn(text);
return;
}
/* clear map */
fillcol = SDL_MapRGB(buffer->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b);
SDL_FillRect(buffer, NULL, fillcol);
/* draw all objects links etc*/
for (i = 0; i < map[curmap].numthings; i++) {
if (map[curmap].thing[i].type == T_OBJECT) {
if (testing) {
printf("Drawing thing #%d (%d, %s)\n",i,map[curmap].thing[i].id,objtype[map[curmap].obj[map[curmap].thing[i].id].type].name);
fflush(stdout);
}
drawobject(buffer, &map[curmap].obj[map[curmap].thing[i].id]);
} else if (map[curmap].thing[i].type == T_LINK) {
if (testing) {
printf ("Drawing thing #%d (%d, link)\n",i,map[curmap].thing[i].id);
fflush(stdout);
}
drawlink(buffer, &map[curmap].olink[map[curmap].thing[i].id]);
} else if (map[curmap].thing[i].type == T_TEXT) {
if (testing) {
printf ("Drawing thing #%d (%d, text)\n",i,map[curmap].thing[i].id);
fflush(stdout);
}
drawtext(buffer, &map[curmap].textob[map[curmap].thing[i].id]);
} else {
printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type);
fflush(stdout);
}
}
/* highlight the selected object */
/* by drawing boxes in its corners */
if (map[curmap].selecteditem != -1) {
if (map[curmap].selecteditemtype == T_OBJECT) {
/* 10% of map[curmap].object's size */
area.w = map[curmap].obj[map[curmap].selecteditem].w / OBJSELHANDLEPCT;
area.h = map[curmap].obj[map[curmap].selecteditem].h / OBJSELHANDLEPCT;
if (area.w < 2) area.w = 2;
if (area.h < 2) area.h = 2;
fillcol = SDL_MapRGB(buffer->format, 0, 0, 0);
/* top left */
area.x = map[curmap].obj[map[curmap].selecteditem].x; area.y = map[curmap].obj[map[curmap].selecteditem].y;
SDL_FillRect(buffer, &area, fillcol);
/* top right */
area.x = map[curmap].obj[map[curmap].selecteditem].x + map[curmap].obj[map[curmap].selecteditem].w - area.w; area.y = map[curmap].obj[map[curmap].selecteditem].y;
SDL_FillRect(buffer, &area, fillcol);
/* bottom left */
area.x = map[curmap].obj[map[curmap].selecteditem].x ; area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
/* bottom right */
area.x = map[curmap].obj[map[curmap].selecteditem].x + map[curmap].obj[map[curmap].selecteditem].w - area.w; area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
} else if (map[curmap].selecteditemtype == T_TEXT) {
/* 10% of text's size */
area.w = map[curmap].textob[map[curmap].selecteditem].w / OBJSELHANDLEPCT;
area.h = map[curmap].textob[map[curmap].selecteditem].h / OBJSELHANDLEPCT;
if (area.w < 2) area.w = 2;
if (area.h < 2) area.h = 2;
anchoreditem = map[curmap].textob[map[curmap].selecteditem].anchor;
if (anchoreditem == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[anchoreditem].x;
tyoff = map[curmap].obj[anchoreditem].y;
}
fillcol = SDL_MapRGB(buffer->format, 0, 0, 0);
/* top left */
area.x = map[curmap].textob[map[curmap].selecteditem].x + txoff; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff;
SDL_FillRect(buffer, &area, fillcol);
/* top right */
area.x = map[curmap].textob[map[curmap].selecteditem].x +txoff + map[curmap].textob[map[curmap].selecteditem].w - area.w; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff;
SDL_FillRect(buffer, &area, fillcol);
/* bottom left */
area.x = map[curmap].textob[map[curmap].selecteditem].x +txoff ; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff +map[curmap].textob[map[curmap].selecteditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
/* bottom right */
area.x = map[curmap].textob[map[curmap].selecteditem].x+txoff + map[curmap].textob[map[curmap].selecteditem].w - area.w; area.y = map[curmap].textob[map[curmap].selecteditem].y +tyoff+ map[curmap].textob[map[curmap].selecteditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
/* if this text is anchored, highlight the map[curmap].object which it is anchored to */
if (anchoreditem != -1) {
area.w = map[curmap].obj[anchoreditem].w / OBJSELHANDLEPCT;
area.h = map[curmap].obj[anchoreditem].h / OBJSELHANDLEPCT;
if (area.w < 2) area.w = 2;
if (area.h < 2) area.h = 2;
fillcol = SDL_MapRGB(buffer->format, 0, 255, 0);
/* top left */
area.x = map[curmap].obj[anchoreditem].x; area.y = map[curmap].obj[anchoreditem].y;
SDL_FillRect(buffer, &area, fillcol);
/* top right */
area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w; area.y = map[curmap].obj[anchoreditem].y;
SDL_FillRect(buffer, &area, fillcol);
/* bottom left */
area.x = map[curmap].obj[anchoreditem].x ; area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
/* bottom right */
area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w; area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h;
SDL_FillRect(buffer, &area, fillcol);
}
} else if (map[curmap].selecteditemtype == T_LINK) {
/* 10% of map[curmap].object's size */
area.w = LINESELHANDLESIZE;
area.h = LINESELHANDLESIZE;
fillcol = SDL_MapRGB(buffer->format, 0, 0, 0);
/* start of line */
area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].x + map[curmap].olink[map[curmap].selecteditem].srcxoff - (LINESELHANDLESIZE/2);
area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
/* end of line */
area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].x + map[curmap].olink[map[curmap].selecteditem].dstxoff - (LINESELHANDLESIZE/2);
area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
/* points on the line */
for (i = 0; i < map[curmap].olink[map[curmap].selecteditem].npoints; i++) {
area.x = map[curmap].olink[map[curmap].selecteditem].point[i].x - (LINESELHANDLESIZE/2);
area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
}
} else if (map[curmap].selecteditemtype == T_LINKPOINT) {
/* highlight the line in green */
/* 10% of map[curmap].object's size */
area.w = LINESELHANDLESIZE;
area.h = LINESELHANDLESIZE;
fillcol = SDL_MapRGB(buffer->format, 0, 255, 0);
/* start of line */
area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].x + map[curmap].olink[map[curmap].selecteditem].srcxoff - (LINESELHANDLESIZE/2);
area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
/* end of line */
area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].x + map[curmap].olink[map[curmap].selecteditem].dstxoff - (LINESELHANDLESIZE/2);
area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
/* points on the line */
for (i = 0; i < map[curmap].olink[map[curmap].selecteditem].npoints; i++) {
if (i == map[curmap].selectedlinkpoint) {
fillcol = SDL_MapRGB(buffer->format, 0, 0, 0);
} else {
fillcol = SDL_MapRGB(buffer->format, 0, 255, 0);
}
area.x = map[curmap].olink[map[curmap].selecteditem].point[i].x - (LINESELHANDLESIZE/2);
area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2);
SDL_FillRect(buffer, &area, fillcol);
}
}
}
/* blit buffer to screen */
SDL_BlitSurface(buffer, 0, screen,0);
drawmapbox();
/* draw status bar */
drawstatusbar();
/* flip */
SDL_UpdateRect(screen, 0, 0, map[curmap].width, map[curmap].height);
}
void drawstatusbar(void) {
//int x,y;
Uint32 col;
SDL_Rect area;
text_t temp;
col = SDL_MapRGB(screen->format, map[curmap].bgcol.r, map[curmap].bgcol.g, map[curmap].bgcol.b);
area.x = 0;
area.y = map[curmap].height;
area.w = map[curmap].width;
area.h = map[curmap].height + DEFTEXTH + 3;
SDL_FillRect(screen, &area, col);
drawline(screen, 0, map[curmap].height, map[curmap].width, map[curmap].height, blue);
/* strip newlines from text */
if (statustext[strlen(statustext)-1] == '\n')
statustext[strlen(statustext)-1] = '\0';
strcpy(temp.text, statustext);
temp.x = 2;
temp.y = map[curmap].height+2;
temp.w = strlen(temp.text) * DEFTEXTW;
temp.h = DEFTEXTH;
temp.c = black;
temp.anchor = -1;
drawtext(screen, &temp);
/* show modified status */
if (modified) {
temp.x = map[curmap].width - 25;
temp.y = map[curmap].height+2;
temp.w = 20;
temp.h = DEFTEXTH;
temp.c = blue;
temp.anchor = -1;
strcpy(temp.text, "MOD");
drawbox(screen, temp.x-3,temp.y-1,temp.x+temp.w+1,temp.y+temp.h+1,blue);
drawtext(screen, &temp);
}
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
}
void drawmapbox(void) {
text_t temp;
int x,y;
int i;
int lh = DEFTEXTH -2;
int found;
int n;
Uint32 fillcol;
SDL_Rect area;
x = mapbox.x+1;
y = mapbox.y+1;
/* clear it */
area.x = mapbox.x;
area.y = mapbox.y;
area.w = screen->w - mapbox.x;
area.h = mapbox.height;
fillcol = SDL_MapRGB(screen->format, 90, 90, 90);
SDL_FillRect(screen, &area, fillcol);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* box around edge */
drawbox(screen, mapbox.x, mapbox.y, mapbox.x + mapbox.width-2,mapbox.y + mapbox.height,white);
/* current map */
sprintf(temp.text, map[curmap].name);
temp.x = x;
temp.y = y;
temp.w = strlen(temp.text) * DEFTEXTW;
temp.h = lh;
temp.anchor = -1;
temp.c = white;
drawtext(screen, &temp);
y += DEFTEXTH;
/* seperator line */
drawline(screen, x, y, x+mapbox.width-2, y, white);
y++;
/* show .. */
if (numhistory >= 1) {
/* draw arrow */
drawline(screen, x+5,y+(DEFTEXTH/2),x+mapbox.width-15,y+(DEFTEXTH/2),white);
drawline(screen, x+5,y+(DEFTEXTH/2),x+15,y+1,white);
drawline(screen, x+5,y+(DEFTEXTH/2),x+15,y+(DEFTEXTH-1),white);
}
y += DEFTEXTH;
/* children ... */
numchildren = 0;
for (i = 0; i < map[curmap].numobjects; i++) {
if (map[curmap].obj[i].child != -1) {
/* make sure we haven't already drawn this name */
found = FALSE;
for (n = 0; n < numchildren; n++) {
if (children[n] == map[curmap].obj[i].child) {
found = TRUE;
break;
}
}
if (!found) {
sprintf(temp.text, map[map[curmap].obj[i].child].name);
//temp.x = x+DEFTEXTW;
temp.x = x;
temp.y = y;
temp.w = strlen(temp.text) * DEFTEXTW;
temp.h = lh;
temp.anchor = -1;
temp.c = white;
drawtext(screen, &temp);
children[numchildren] = map[curmap].obj[i].child;
numchildren++;
y += DEFTEXTH;
}
}
}
SDL_UpdateRect(screen, mapbox.x, mapbox.y, screen->w - mapbox.x,mapbox.height+2);
//SDL_Flip(screen);
}
void drawmaplist(SDL_Surface *dest) {
int x,y;
int i;
text_t temp;
Uint32 fillcol;
SDL_Rect area;
/* clear screen*/
fillcol = SDL_MapRGB(screen->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b);
area.x = 0;
area.y = 0;
area.w = map[curmap].width;
area.h = map[curmap].height-1;
SDL_FillRect(screen, &area, fillcol);
x = 10;
y = 10;
strcpy(temp.text, "Select map to link to:");
temp.x = x;
temp.y = y;
temp.w = strlen(temp.text) * (DEFTEXTW*2);
temp.h = DEFTEXTH*2;
temp.c = black;
temp.anchor = -1;
drawtext(dest, &temp);
y = 50;
drawbox(dest, x, y, map[curmap].width-1,y+(DEFTEXTH*2),blue);
strcpy(temp.text, "(none)");
temp.x = x+1;
temp.y = y+1;
temp.w = strlen(temp.text) * (DEFTEXTW*2);
temp.h = (DEFTEXTH*2)-2;
temp.c = blue;
temp.anchor = -1;
drawtext(dest, &temp);
y += (DEFTEXTH*2);
for (i = 0; i < nummaps; i++) {
drawbox(dest, x, y, map[curmap].width-1,y+(DEFTEXTH*2),blue);
strcpy(temp.text, map[i].name);
temp.x = x+1;
temp.y = y+1;
temp.w = strlen(temp.text) * (DEFTEXTW*2);
temp.h = (DEFTEXTH*2)-2;
temp.c = blue;
temp.anchor = -1;
drawtext(dest, &temp);
y += (DEFTEXTH*2);
}
SDL_Flip(screen);
}
void drawobox(void) {
int x,y,i;
SDL_Rect area;
mapobject_t temp;
Uint32 fillcol;
SDL_Color outlinecol;
int outlinepos;
int fitx,fity,fit;
fillcol = SDL_MapRGB(screen->format, obox.bgcol.r,obox.bgcol.g,obox.bgcol.b);
area.x = obox.x;
area.y = obox.y;
area.w = obox.width;
area.h = obox.height+3;
SDL_FillRect(screen, &area, fillcol);
x = obox.x;
y = obox.y;
/* calculate how many items we can fit in the obox */
/* figure out how many objects we can fit in the box */
fitx = (obox.width / obox.gridsize);
fity = ((obox.height+3) / obox.gridsize);
fit = fitx * fity;
for (i = (obox.pos*3); i < numobjtypes; i++) {
if ((x + obox.gridsize) >= (map[curmap].width + SIDEBARW)) {
x = obox.x;
if ((y + obox.gridsize) >= (map[curmap].height)) {
break;
}
y += obox.gridsize;
}
/* draw box */
outlinecol = obox.gridcol;
drawline(screen, x, y,x+obox.gridsize,y,outlinecol); /* top */
drawline(screen, x, y+obox.gridsize,x+obox.gridsize,y+obox.gridsize,outlinecol); /* bottom */
drawline(screen, x, y,x,y+obox.gridsize,outlinecol); /* left */
drawline(screen, x+obox.gridsize, y,x+obox.gridsize,y+obox.gridsize,outlinecol); /* right */
/* fill it */
fillcol = SDL_MapRGB(screen->format, obox.gridbgcol.r,obox.gridbgcol.g,obox.gridbgcol.b);
area.x = x+1;
area.y = y+1;
area.w = obox.gridsize-1;
area.h = obox.gridsize-1;
SDL_FillRect(screen, &area, fillcol);
/* draw map[curmap].object */
temp.type = i;
temp.x = x+1;
temp.y = y+1;
temp.w = obox.gridsize-2;
temp.h = obox.gridsize-2;
drawobject(screen, &temp);
//SDL_UpdateRect(screen, x, y, obox.gridsize+1,obox.gridsize+1);
x += obox.gridsize;
}
/* oooo */
/* draw selector */
outlinecol = red;
outlinepos = map[curmap].selectedtype - (obox.pos*3);
if ((outlinepos >= 0) && (outlinepos < fit)) {
y = ((map[curmap].selectedtype - (obox.pos*3)) / obox.gridrowlen) * obox.gridsize + obox.y;
x = ((map[curmap].selectedtype - (obox.pos*3)) % obox.gridrowlen) * obox.gridsize + obox.x;
drawline(screen, x, y,x+obox.gridsize,y,outlinecol); /* top */
drawline(screen, x, y+obox.gridsize,x+obox.gridsize,y+obox.gridsize,outlinecol); /* bottom */
drawline(screen, x, y,x,y+obox.gridsize,outlinecol); /* left */
drawline(screen, x+obox.gridsize, y,x+obox.gridsize,y+obox.gridsize,outlinecol); /* right */
}
//SDL_UpdateRect(screen, x, y, obox.gridsize+1,obox.gridsize+1);
SDL_UpdateRect(screen,obox.x, obox.y, obox.width-1, obox.height+3);
}
void drawscreen(void){
sprintf(statustext, "Welcome to netmapr v%s.", VERSION);
drawmap();
drawtoolbox();
drawobox();
}
void drawtext(SDL_Surface *dest, text_t *t) {
int x,y;
int tw,th;
int i;
int txoff,tyoff;
if (strlen(t->text) == 0) {
return;
}
/* calculate letter width, letter height */
tw = t->w / strlen(t->text);
//tw = DEFTEXTW;
th = t->h;
if (t->anchor == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[t->anchor].x;
tyoff = map[curmap].obj[t->anchor].y;
}
//printf("drawtext() of: '%s' (len %d)\n",t->text, strlen(t->text)); fflush(stdout);
for (i = 0; i < strlen(t->text); i++) {
x = t->x + (i * tw) + txoff;
y = t->y + tyoff;
if (drawletter(dest, x, y, tw, th, t->text[i], t->c) ) {
if (t->text[i] != ' ') {
printf("INVALID letter: '%c'\n",t->text[i]); fflush(stdout);
}
} else {
//printf("drawing letter: '%c' at %d,%d\n",t->text[i],x, t->y); fflush(stdout);
}
}
}
void drawtoolbox(void) {
int x,y,i;
SDL_Rect area;
Uint32 fillcol;
Uint32 bcol;
int z;
SDL_Color gridhigh = {255, 255, 255, 0};
SDL_Color gridmiddle = {90, 90, 90, 0};
SDL_Color gridlow = {50, 50, 50, 0};
fillcol = SDL_MapRGB(screen->format, toolbox.bgcol.r,toolbox.bgcol.g,toolbox.bgcol.b);
area.x = toolbox.x;
area.y = toolbox.y;
area.w = toolbox.width;
area.h = toolbox.height;
SDL_FillRect(screen, &area, fillcol);
x = toolbox.x;
y = toolbox.y;
/* draw each button */
for (i = 0; i < numbuttons; i++) {
if ((x + toolbox.gridsize) >= (map[curmap].width + SIDEBARW)) {
x = toolbox.x;
y += toolbox.gridsize+3;
if ((y + toolbox.gridsize) >= (toolbox.height)) {
break;
}
}
/* draw box */
drawline(screen, x, y,x+toolbox.gridsize,y,gridhigh); /* top */
drawline(screen, x, y+1,x+toolbox.gridsize,y+1,gridhigh); /* top */
drawline(screen, x, y+toolbox.gridsize-1,x+toolbox.gridsize,y+toolbox.gridsize-1,gridlow); /* bottom */
drawline(screen, x, y+toolbox.gridsize,x+toolbox.gridsize,y+toolbox.gridsize,gridlow); /* bottom */
drawline(screen, x, y,x,y+toolbox.gridsize,gridhigh); /* left */
drawline(screen, x+1, y,x+1,y+toolbox.gridsize-1,gridhigh); /* left */
drawline(screen, x+toolbox.gridsize, y+1,x+toolbox.gridsize,y+toolbox.gridsize,gridlow); /* right */
drawline(screen, x+toolbox.gridsize-1, y+1,x+toolbox.gridsize-1,y+toolbox.gridsize,gridlow); /* right */
for (z = y+2; z < y+toolbox.gridsize;z++) {
drawline(screen,x+2,z,x+toolbox.gridsize-2,z,gridmiddle);
}
area.x = x+2;
area.y = y+2;
area.w = toolbox.gridsize-4;
area.h = toolbox.gridsize-4;
/* set transparent colour on temp surface */
bcol = SDL_MapRGB(buffer->format, 0, 0, 0);
/* blit button image onto button */
SDL_SetColorKey(button[i].img, SDL_SRCCOLORKEY|SDL_RLEACCEL, bcol);
SDL_BlitSurface(button[i].img, 0, screen, &area);
/* special cases */
if (i == TB_FGCOL) {
floodfill(screen, area.x + 5, area.y + 5, fgcol);
}
if (i == TB_FILLCOL) {
floodfill(screen, area.x + 5, area.y + 5, objfillcol);
}
SDL_UpdateRect(screen, x, y, toolbox.gridsize+3,toolbox.gridsize+3);
x += toolbox.gridsize+3;
}
/* draw selectors */
if (state == S_NONE) drawtoolboxselector(TB_POINTER);
if (state == S_ADDOBJ) drawtoolboxselector(TB_ADDOBJ);
if (state == S_ADDTEXT) drawtoolboxselector(TB_ADDTEXT);
if (state == S_SAVING) drawtoolboxselector(TB_SAVE);
if (state == S_LOADING) drawtoolboxselector(TB_LOAD);
if (state == S_MATCHSIZE) drawtoolboxselector(TB_MATCHSIZE);
if (state == S_MATCHX) drawtoolboxselector(TB_MATCHX);
if (state == S_MATCHY) drawtoolboxselector(TB_MATCHY);
if (state == S_CREATETELE) drawtoolboxselector(TB_CREATETELE);
}
void drawtoolboxselector(int buttonid) {
SDL_Color outlinecol;
int x,y;
/* draw selector */
outlinecol = red;
y = (buttonid / toolbox.gridrowlen) * (toolbox.gridsize+3) + toolbox.y;
x = (buttonid % toolbox.gridrowlen) * (toolbox.gridsize+3) + toolbox.x;
drawline(screen, x, y,x+toolbox.gridsize,y,outlinecol); /* top */
drawline(screen, x, y+1,x+toolbox.gridsize,y+1,outlinecol); /* top */
drawline(screen, x, y+toolbox.gridsize,x+toolbox.gridsize,y+toolbox.gridsize,outlinecol); /* bottom */
drawline(screen, x, y+toolbox.gridsize-1,x+toolbox.gridsize,y+toolbox.gridsize-1,outlinecol); /* bottom */
drawline(screen, x, y,x,y+toolbox.gridsize,outlinecol); /* left */
drawline(screen, x+1, y,x+1,y+toolbox.gridsize,outlinecol); /* left */
drawline(screen, x+toolbox.gridsize, y,x+toolbox.gridsize,y+toolbox.gridsize,outlinecol); /* right */
drawline(screen, x+toolbox.gridsize-1, y,x+toolbox.gridsize-1,y+toolbox.gridsize,outlinecol); /* right */
SDL_UpdateRect(screen, x, y, toolbox.gridsize+3,toolbox.gridsize+3);
}
void drawvector(SDL_Surface *dest, vectorimg_t *vimg, int x, int y, int w, int h, SDL_Color *overridefg) {
float xscale,yscale;
int realx1, realy1;
int realx2, realy2;
int i;
SDL_Color linecol,fillcol;
xscale = (float)w / (float)vimg->w;
yscale = (float)h / (float)vimg->h;
for (i = 0; i < vimg->vnum; i++) {
// select colour
if (overridefg == NULL) {
if (vimg->vector[i].c.unused == 255) {
linecol = fgcol;
} else {
linecol = vimg->vector[i].c;
}
} else {
linecol = *overridefg;
}
if (vimg->vector[i].c.unused == 255) {
fillcol = objfillcol;
} else {
fillcol = vimg->vector[i].c;
}
// scale the coords of this vector
realx1 = x + ((float)vimg->vector[i].x1 * xscale);
realy1 = y + ((float)vimg->vector[i].y1 * yscale);
realx2 = x + ((float)vimg->vector[i].x2 * xscale);
realy2 = y + ((float)vimg->vector[i].y2 * yscale);
// draw this vector
switch (vimg->vector[i].type) {
case VT_LINE:
drawline(dest,realx1,realy1, realx2,realy2,linecol);
break;
case VT_BOX:
drawbox(dest,realx1,realy1, realx2,realy2,linecol);
break;
case VT_FILL:
floodfill(dest,realx1,realy1, fillcol);
break;
}
}
}
int endtext(void) {
SDL_Rect area;
/* paste old background */
if (bg != NULL) {
area.x = bgx;
area.y = bgy;
area.w = bg->w;
area.h = bg->h;
SDL_BlitSurface(bg,0,screen, &area);
SDL_UpdateRect(screen, bgx, bgy, bg->w, bg->h);
// free it
SDL_FreeSurface(bg);
}
if (strlen(text) == 0) {
return TRUE;
}
strcpy(map[curmap].textob[map[curmap].numtext].text, text);
map[curmap].textob[map[curmap].numtext].anchor = textanchor;
if (map[curmap].textob[map[curmap].numtext].anchor == -1) {
/* x,y = normal (ie. offset from 0,0) */
map[curmap].textob[map[curmap].numtext].x = startx;
map[curmap].textob[map[curmap].numtext].y = starty;
} else {
/* x,y = offset from anchor map[curmap].object's coordinates */
map[curmap].textob[map[curmap].numtext].x = startx - map[curmap].obj[textanchor].x;
map[curmap].textob[map[curmap].numtext].y = starty - map[curmap].obj[textanchor].y;
}
map[curmap].textob[map[curmap].numtext].w = strlen(text) * (DEFTEXTW);
map[curmap].textob[map[curmap].numtext].h = DEFTEXTH;
map[curmap].textob[map[curmap].numtext].c = fgcol;
/* add to 'thing' list */
map[curmap].thing[map[curmap].numthings].type = T_TEXT;
map[curmap].thing[map[curmap].numthings].id = map[curmap].numtext;
modified = TRUE;
sprintf(statustext,"Added text object #%d: '%s'\n",map[curmap].numtext, map[curmap].textob[map[curmap].numtext].text);
drawstatusbar();
map[curmap].numtext++;
map[curmap].numthings++;
changestate(S_NONE);
drawmap();
return FALSE;
}
int endtextmove(int x, int y) {
int txoff,tyoff;
SDL_FreeSurface(bg);
if (map[curmap].textob[map[curmap].curtext].anchor == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].x;
tyoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].y;
}
/* check position */
if ((map[curmap].textob[map[curmap].curtext].x + txoff + x - startx) >= (map[curmap].width - map[curmap].textob[map[curmap].curtext].w)) {
return -1;
}
if ((map[curmap].textob[map[curmap].curtext].y + tyoff + y - starty) >= (map[curmap].height - map[curmap].textob[map[curmap].curtext].h)) {
return -1;
}
if (map[curmap].textob[map[curmap].curtext].x + txoff <= 0) {
return -1;
}
if (map[curmap].textob[map[curmap].curtext].y + tyoff <= 0) {
return -1;
}
map[curmap].textob[map[curmap].curtext].x += (x - startx);
map[curmap].textob[map[curmap].curtext].y += (y - starty);
modified = TRUE;
return 0;
}
void floodfill(SDL_Surface *dest, int x, int y, SDL_Color fillcol) {
int testing;
SDL_Color bgcolor;
testing = 0;
//XXX: testing
if (testing) {
drawpixel(dest, x, y, fillcol);
} else {
getcolor(dest, x,y,&bgcolor);
if ((bgcolor.r == fillcol.r) && (bgcolor.g == fillcol.g) && (bgcolor.b == fillcol.b)) {
return;
}
floodfill4(dest, x, y, fillcol, bgcolor);
}
}
void push(int x, int y) {
fillstack[fillstackptr].x = x;
fillstack[fillstackptr].y = y;
fillstackptr++;
}
void pop(int *x, int *y) {
fillstackptr--;
*x = fillstack[fillstackptr].x;
*y = fillstack[fillstackptr].y;
}
void floodfill4(SDL_Surface *dest, int x, int y, SDL_Color fillcol, SDL_Color bgcol) {
SDL_Color curcolor;
push(x,y);
while (fillstackptr != 0) {
pop(&x,&y);
getcolor(dest, x,y,&curcolor);
if ((curcolor.r == bgcol.r) && (curcolor.g == bgcol.g) && (curcolor.b == bgcol.b)) {
drawpixel(dest, x, y, fillcol);
}
if (x > 0) {
getcolor(dest, x-1,y,&curcolor);
if ((curcolor.r == bgcol.r) && (curcolor.g == bgcol.g) && (curcolor.b == bgcol.b)) {
push(x-1,y);
}
}
if (y > 0) {
getcolor(dest, x,y-1,&curcolor);
if ((curcolor.r == bgcol.r) && (curcolor.g == bgcol.g) && (curcolor.b == bgcol.b)) {
push(x,y-1);
}
}
if (x < (dest->w -1)) {
getcolor(dest, x+1,y,&curcolor);
if ((curcolor.r == bgcol.r) && (curcolor.g == bgcol.g) && (curcolor.b == bgcol.b)) {
push(x+1,y);
}
}
if (y < (dest->h -1)) {
getcolor(dest, x,y+1,&curcolor);
if ((curcolor.r == bgcol.r) && (curcolor.g == bgcol.g) && (curcolor.b == bgcol.b)) {
push(x,y+1);
}
}
}
}
int getcolor(SDL_Surface *dest, int x, int y, SDL_Color *col) {
Uint32 *pixel;
int bpp;
/* SHOULD ALWAYS BE 2!! */
bpp = dest->format->BytesPerPixel;
if (bpp != 2) {
printf("bpp isnt 2!!!\n");
fflush(stdout);
}
//pixel = (Uint32 *) (dest->pixels + (y * dest->w) + x) ;
pixel = (Uint32 *) (dest->pixels + y * dest->pitch + x * bpp);
SDL_GetRGB(*pixel,dest->format,
&col->r,
&col->g,
&col->b );
return 0;
}
void drawyn(char *prompt) {
SDL_Rect area;
text_t text;
/* clear map to red */
area.x = 0;
area.y = 0;
area.w = map[curmap].width;
area.h = map[curmap].height-1;
SDL_FillRect(screen, &area, SDL_MapRGB(screen->format, 255, 0, 0));
drawbox(screen, 0, 200,399,500,blue);
drawbox(screen, 400, 200,799,500,blue);
text.w = strlen(prompt)*DEFTEXTW*2;
text.h = 50;
text.x = (map[curmap].width/2) - (text.w/2);
text.y = 100;
text.anchor = -1;
text.c = blue;
strcpy(text.text, prompt);
drawtext(screen, &text);
/* draw yes & no */
text.x = 50;
text.y = 300;
text.w = 300;
text.h = 100;
text.anchor = -1;
text.c = blue;
strcpy(text.text, "Yes");
drawtext(screen, &text);
text.x = 500;
text.y = 300;
text.w = 200;
text.h = 100;
text.anchor = -1;
text.c = blue;
strcpy(text.text, "No");
drawtext(screen, &text);
SDL_Flip(screen);
}
int getyn(int x, int y) {
if ((x >= 0) && (x <= 399) && (y >= 200) && (y <= 500)) {
return YES;
} else if ((x >= 400) && (x <= 799) && (y >= 200) && (y <= 500)) {
return NO;
}
return MAYBE;
}
void goback(void) {
if (numhistory >= 1) {
curmap = history[numhistory-1];
numhistory--;
sprintf(statustext, "Changed map to map #%d (%s).",curmap,map[curmap].name);
drawmap();
} else {
sprintf(statustext, "Already at top level!");
drawstatusbar();
}
}
int linelen(int x1,int y1,int x2,int y2) {
int deltax, deltay;
int numpixels;
int d;
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
numpixels = deltax + 1;
d = (deltay*2) - deltax;
dinc1 = deltay << 1;
dinc2 = (deltay-deltax) << 1;
xinc1 = 1;
xinc2 = 1;
yinc1 = 0;
yinc2 = 1;
} else {
numpixels = deltay + 1;
d = (deltax*2) - deltay;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
xinc1 = 0;
xinc2 = 1;
yinc1 = 1;
yinc2 = 1;
}
return numpixels;
}
int linkat(int x, int y) {
int i;
for (i = 0; i < map[curmap].numlinks; i++) {
/* is (x,y) on the line? */
if (isonlink(i, x, y)) return i;
}
return -1;
}
int loadmap(void) {
char filename[BUFLEN];
FILE *f;
int namelen;
int i;
/* TODO: validate */
strcpy(filename, text);
sprintf(statustext,"Loading map...\n");
drawstatusbar();
f = fopen(filename, "rb");
if (!f) {
sprintf(statustext,"ERROR: Cannot open '%s'.\n",filename);
return TRUE;
}
/* TODO: free() variables! */
/* read in number maps */
fread(&nummaps, sizeof(int), 1, f);
for (i = 0; i < nummaps; i++) {
fread(&map[i].width, sizeof(int), 1, f);
fread(&map[i].height, sizeof(int), 1, f);
fread(&map[i].bpp, sizeof(int), 1, f);
fread(&map[i].bgcol, sizeof(SDL_Color), 1, f);
fread(&map[i].boxcol, sizeof(SDL_Color), 1, f);
fread(&map[i].numthings, sizeof(int), 1, f);
fread(&map[i].numobjects, sizeof(int), 1, f);
fread(&map[i].numlinks, sizeof(int), 1, f);
fread(&map[i].numtext, sizeof(int), 1, f);
map[i].selecteditem = -1;
map[i].selecteditemtype = -1;
map[i].selectedlinkpoint = -1;
map[i].selectedtype = 0;
map[i].curobj = -1;
map[i].curlink = -1;
map[i].curlinkpoint = -1;
map[i].curtext = -1;
map[i].startx = -1;
map[i].starty = -1;
map[i].textanchor = -1;
strcpy(map[i].text, "");
fread(&namelen, sizeof(int), 1, f);
fread(&map[i].name, (namelen+1) * sizeof(char), 1, f);
/* read objects */
fread(&map[i].thing, sizeof(thing_t), map[i].numthings, f);
fread(&map[i].olink, sizeof(link_t), map[i].numlinks, f);
fread(&map[i].obj, sizeof(mapobject_t), map[i].numobjects, f);
fread(&map[i].textob, sizeof(text_t), map[i].numtext, f);
}
fclose(f);
curmap = 0;
modified = FALSE;
sprintf(statustext,"Successfully loaded map from '%s' (%d maps).\n",filename,nummaps); fflush(stdout);
strcpy(currentfilename, filename);
drawmap();
return FALSE;
}
void lowerselected(void) {
int i;
int temptype,tempid;
int target;
/* find map[curmap].object */
for (i = 0; i < map[curmap].numthings; i++) {
if ((map[curmap].thing[i].id == map[curmap].selecteditem) && (map[curmap].thing[i].type == map[curmap].selecteditemtype)) {
/* swap with one below */
if (i == 0) {
break;
} else {
target = i-1;
}
tempid = map[curmap].thing[target].id;
temptype = map[curmap].thing[target].type;
map[curmap].thing[target].id = map[curmap].thing[i].id;
map[curmap].thing[target].type = map[curmap].thing[i].type;
map[curmap].thing[i].id = tempid;
map[curmap].thing[i].type = temptype;
break;
}
}
modified = TRUE;
/* redraw map */
drawmap();
}
int objat(int x, int y) {
int i;
for (i = 0; i < map[curmap].numobjects; i++) {
if ( (x >= map[curmap].obj[i].x ) && (x <= (map[curmap].obj[i].x + map[curmap].obj[i].w)) &&
(y >= map[curmap].obj[i].y ) && (y <= (map[curmap].obj[i].y + map[curmap].obj[i].h)) ) {
return i;
}
}
return -1;
}
void pasteline(SDL_Surface *screen, int *lbuf) {
int deltax, deltay;
int numpixels;
int d;
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
int i;
int x;
int y;
SDL_Color bgcol;
int x1,y1,x2,y2;
int tlx,tly,w,h;
x1 = lbuf[0];
y1 = lbuf[1];
x2 = lbuf[2];
y2 = lbuf[3];
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
numpixels = deltax + 1;
d = (deltay*2) - deltax;
dinc1 = deltay << 1;
dinc2 = (deltay-deltax) << 1;
xinc1 = 1;
xinc2 = 1;
yinc1 = 0;
yinc2 = 1;
} else {
numpixels = deltay + 1;
d = (deltax*2) - deltay;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
xinc1 = 0;
xinc2 = 1;
yinc1 = 1;
yinc2 = 1;
}
if (x1 > x2) {
xinc1 = - xinc1;
xinc2 = - xinc2;
}
if (y1 > y2) {
yinc1 = - yinc1;
yinc2 = - yinc2;
}
x = x1; y = y1;
for (i = 0; i < numpixels; i++) {
SDL_GetRGB(lbuf[i+4],screen->format,
&bgcol.r,
&bgcol.g,
&bgcol.b );
drawpixel(screen, x, y, bgcol);
if (d < 0) {
d += dinc1;
x += xinc1;
y += yinc1;
} else {
d += dinc2;
x += xinc2;
y += yinc2;
}
}
/* update screen */
x1 = lbuf[0];
y1 = lbuf[1];
x2 = lbuf[2];
y2 = lbuf[3];
if (x2 < x1) {
if (y2 < y1) {
tlx = x2;
tly = y2;
w = x1 - x2;
h = y1 - y2;
} else {
tlx = x2;
tly = y1;
w = x1 - x2;
h = y2 - y1;
}
} else {
if (y2 < y1) {
tlx = x1;
tly = y2;
w = x2 - x1;
h = y1 - y2;
} else {
tlx = x1;
tly = y1;
w = x2 - x1;
h = y2 - y1;
}
}
SDL_UpdateRect(screen, tlx, tly,w,h);
}
int initgraphics(void) {
FILE *f;
char *p;
int line;
int state;
int n;
vectorimg_t tempv;
char buf[BUFLEN];
int x,y;
Uint8 data[32];
Uint8 mask[32];
int i;
char verstring[BUFLEN];
char file[BUFLEN];
int x1,x2,y1,y2;
SDL_Color c;
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) {
printf("SDL_Init: %s\n", SDL_GetError());
exit(1);
}
initvars();
/* initialise mouse cursors */
/* regular cursor */
normalmouse = SDL_GetCursor();
/* object placement cursor */
for (i = 0; i < 32; i++) {
data[i] = normalmouse->data[i];
mask[i] = normalmouse->mask[i];
}
/* add square top+bottom */
for (x = 10; x < 16; x++) {
y = 10;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
y = 15;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
}
/* sides */
for (y = 10; y < 16; y++) {
x = 10;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
x = 15;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
}
objmouse = SDL_CreateCursor(data, mask, normalmouse->area.w, normalmouse->area.h, 0, 0);
/* text placement cursor */
for (i = 0; i < 32; i++) {
data[i] = normalmouse->data[i];
mask[i] = normalmouse->mask[i];
}
/* add A crossstroke*/
for (x = 10; x < 15; x++) {
y = 13;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
}
/* downstrokes */
for (y = 11; y < 16; y++) {
x = 10;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
x = 14;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
}
/* pointy bit */
x = 11; y = 10;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
x = 13; y = 10;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
x = 12; y = 9;
data[(x/8)+(y*2)] |= (128 >> (x%8));
mask[(x/8)+(y*2)] |= (128 >> (x%8));
textmouse = SDL_CreateCursor(data, mask, normalmouse->area.w, normalmouse->area.h, 0, 0);
/* open window */
screen = SDL_SetVideoMode(map[curmap].width + SIDEBARW, map[curmap].height + DEFTEXTH+4, map[curmap].bpp, SDL_HWSURFACE|SDL_DOUBLEBUF);
if(!screen) {
printf("SDL_SetVideoMode: %s\n", SDL_GetError());
return -1;
}
if (screen->flags & SDL_SWSURFACE) {
printf("SWSurface set ok.\n"); fflush(stdout);
}
if (screen->flags & SDL_HWSURFACE) {
printf("HWSurface set ok.\n"); fflush(stdout);
}
if (screen->flags & SDL_DOUBLEBUF) {
printf("Doublebuf set ok.\n"); fflush(stdout);
}
sprintf(verstring, "netmapr v%s, by rpearce 2005", VERSION);
SDL_WM_SetCaption(verstring,"netmapr");
/* initialise buffer */
buffer = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].width,map[curmap].height,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
if (!buffer) {
printf("Cannot create buffer!\n");
exit(1);
}
printf("Reading shapes...\n");
f = fopen("objects.dat","rt");
if (!f) {
sprintf(file, "/usr/local/share/netmapr/objects.dat");
f = fopen(file,"rt");
}
if (!f) {
sprintf(file, "%s/objects.dat",progdir);
f = fopen(file,"rt");
}
if (!f) {
printf("Cannot open objects file!\n");
exit(1);
}
state = 0;
line = 0;
numobjtypes = 0;
n = 0;
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
while (!feof(f)) {
/* ignore comments */
if (buf[0] != '#') {
if (state == 0) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
if (strcmp(p, "object")) {
printf("Expecting 'object' on line #%d of objects file (got '%s').\n",line,p);
exit(1);
}
/* name */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
strncpy(objtype[numobjtypes].name, p, BUFLEN);
/* width */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
objtype[numobjtypes].vimg.w = atoi(p);
/* height */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
objtype[numobjtypes].vimg.h = atoi(p);
/* no vectors to start with */
objtype[numobjtypes].vimg.vnum = 0;
objtype[numobjtypes].canscale = TRUE;
/* default size is minimum */
objtype[numobjtypes].defw = MINOBJWIDTH;
objtype[numobjtypes].defh = MINOBJHEIGHT;
state = 1;
} else if (state == 1) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
if (!strcmp(p, "line")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
y2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&objtype[numobjtypes].vimg,VT_LINE,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of objects file.\n",line);
exit(1);
}
} else if (!strcmp(p, "fill")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&objtype[numobjtypes].vimg,VT_FILL,x1,y1,0,0,&c)) {
printf("Too many vectors on line %d of objects file.\n",line);
exit(1);
}
} else if (!strcmp(p, "box")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
y2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&objtype[numobjtypes].vimg,VT_BOX,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of objects file.\n",line);
exit(1);
}
} else if (!strcmp(p, "end")) {
state = 0;
numobjtypes++;
if (numobjtypes >= MAXOBJTYPES) {
printf("FATAL: Too many object types found (max is %d).\n",MAXOBJTYPES);
exit(1);
}
} else {
printf("Invalid command '%s' on line #%d of objects file.\n",p,line);
exit(1);
}
}
}
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
}
fclose(f);
printf("Shape load complete - %d objects found.\n",numobjtypes);
printf("Reading buttons...\n");
f = fopen("buttons.dat","rt");
if (!f) {
sprintf(file, "/usr/local/share/netmapr/buttons.dat");
f = fopen(file,"rt");
}
if (!f) {
sprintf(file, "%s/buttons.dat",progdir);
f = fopen(file,"rt");
}
if (!f) {
printf("Cannot open buttons file!\n");
exit(1);
}
state = 0;
line = 0;
numbuttons = 0;
n = 0;
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
while (!feof(f)) {
/* ignore comments */
if (buf[0] != '#') {
if (state == 0) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
if (strcmp(p, "button")) {
printf("Expecting 'button' on line #%d of buttons file (got '%s').\n",line,p);
exit(1);
}
/* name */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
strncpy(button[numbuttons].name, p, BUFLEN);
/* width */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
tempv.w = atoi(p);
/* height */
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
tempv.h = atoi(p);
/* allocate mem */
button[numbuttons].img = SDL_CreateRGBSurface(SDL_SWSURFACE,toolbox.gridsize-2,toolbox.gridsize-2,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
tempv.vnum = 0;
state = 1;
} else if (state == 1) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
if (!strcmp(p, "line")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
y2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&tempv,VT_LINE,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of objects file.\n",line);
exit(1);
}
} else if (!strcmp(p, "fill")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&tempv,VT_FILL,x1,y1,0,0,&c)) {
printf("Too many vectors on line %d of objects file.\n",line);
exit(1);
}
} else if (!strcmp(p, "box")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
y2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.r = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.g = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); }
c.b = atoi(p);
if (addvector(&tempv,VT_BOX,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of buttons file.\n",line);
exit(1);
}
} else if (!strcmp(p, "end")) {
/* draw vector image into button's bitmap field */
drawvector(button[numbuttons].img, &tempv, 1, 1, toolbox.gridsize-2,toolbox.gridsize-2, NULL);
//printf("Adding button: '%s' (vnum = %d).\n",button[numbuttons].name,tempv.vnum);
state = 0;
numbuttons++;
} else {
printf("Invalid command '%s' on line #%d of buttons file.\n",p,line);
exit(1);
}
}
}
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
}
fclose(f);
printf("Button load complete - %d buttons found.\n",numbuttons);
printf("Reading letters...\n");
f = fopen("letters.dat","rt");
if (!f) {
sprintf(file, "/usr/local/share/netmapr/letters.dat");
f = fopen(file,"rt");
}
if (!f) {
sprintf(file, "%s/letters.dat",progdir);
f = fopen(file,"rt");
}
if (!f) {
printf("Cannot open letters file!\n");
exit(1);
}
state = 0;
line = 0;
numletters = 0;
n = 0;
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
while (!feof(f)) {
// ignore comments
if (buf[0] != '#') {
if (state == 0) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
if (strcmp(p, "letter")) {
printf("Expecting 'letter' on line #%d of letters file (got '%s').\n",line,p);
exit(1);
}
// name
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
letter[numletters].name = p[0];
// width
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
letter[numletters].vect.w = atoi(p);
// height
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
letter[numletters].vect.h = atoi(p);
letter[numletters].vect.vnum = 0;
state = 1;
} else if (state == 1) {
p = strtok(buf, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
if (!strcmp(p, "line")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
y2 = atoi(p);
c = fgcol;
if (addvector(&letter[numletters].vect,VT_LINE,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of letters file.\n",line);
exit(1);
}
} else if (!strcmp(p, "fill")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
y1 = atoi(p);
c = fgcol;
if (addvector(&letter[numletters].vect,VT_FILL,x1,y1,0,0,&c)) {
printf("Too many vectors on line %d of letters file.\n",line);
exit(1);
}
} else if (!strcmp(p, "box")) {
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
x1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
y1 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
x2 = atoi(p);
p = strtok(NULL, " ");
if (p == NULL) { printf("Missing token on line #%d of letters file.\n",line); exit(1); }
y2 = atoi(p);
c = fgcol;
if (addvector(&letter[numletters].vect,VT_BOX,x1,y1,x2,y2,&c)) {
printf("Too many vectors on line %d of letters file.\n",line);
exit(1);
}
} else if (!strcmp(p, "end")) {
//printf("Adding letter %d: '%c' (vnum = %d).\n",numletters,letter[numletters].name,letter[numletters].vect.vnum);
state = 0;
numletters++;
if (numletters >= MAXLETTERVECTS) {
printf("FATAL: Too many letters found (max is %d).\n",MAXLETTERVECTS);
exit(1);
}
} else {
printf("Invalid command '%s' on line #%d of letters file.\n",p,line);
exit(1);
}
}
}
fgets(buf, BUFLEN, f);
buf[strlen(buf)-1] = '\0';
line++;
}
fclose(f);
printf("Letter load complete - %d letters found.\n",numletters);
////////////////////////////////////////////////////////////
/// XXX: TESTING ///
/*
x = 10; y = 10;
for (i = 0; i < numletters; i++) {
int lw,lh;
lw = 8;
lh = 10;
drawvector(screen, &letter[i].vect, x, y, lw,lh);
x = x + lw + 2;
if (x >= (map[curmap].width - lw)) {
x = 0;
y = y + lh + 2;
}
}
SDL_Flip(screen);
while(1) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
exit(1);
}
}
}
*/
////////////////////////////////////////////////////////////
return 0;
}
int isonline (int fx, int fy, int x1, int y1, int x2, int y2) {
int deltax, deltay;
int numpixels;
int d;
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
int i;
int x;
int y;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
numpixels = deltax + 1;
d = (deltay*2) - deltax;
dinc1 = deltay << 1;
dinc2 = (deltay-deltax) << 1;
xinc1 = 1;
xinc2 = 1;
yinc1 = 0;
yinc2 = 1;
} else {
numpixels = deltay + 1;
d = (deltax*2) - deltay;
dinc1 = deltax << 1;
dinc2 = (deltax - deltay) << 1;
xinc1 = 0;
xinc2 = 1;
yinc1 = 1;
yinc2 = 1;
}
if (x1 > x2) {
xinc1 = - xinc1;
xinc2 = - xinc2;
}
if (y1 > y2) {
yinc1 = - yinc1;
yinc2 = - yinc2;
}
x = x1; y = y1;
for (i = 0; i < numpixels; i++) {
if ((fx >= (x-LINESELTHRESHOLD)) && (fx <= (x+LINESELTHRESHOLD)) &&
(fy >= (y-LINESELTHRESHOLD)) && (fy <= (y+LINESELTHRESHOLD))) {
return TRUE;
}
if (d < 0) {
d += dinc1;
x += xinc1;
y += yinc1;
} else {
d += dinc2;
x += xinc2;
y += yinc2;
}
}
return FALSE;
}
int isonlink (int linkid, int mx, int my) {
int i;
int x,y,x2,y2;
x = map[curmap].obj[map[curmap].olink[linkid].srcobj].x + map[curmap].olink[linkid].srcxoff;
y = map[curmap].obj[map[curmap].olink[linkid].srcobj].y + map[curmap].olink[linkid].srcyoff;
for (i = 0; i < map[curmap].olink[linkid].npoints; i++) {
x2 = map[curmap].olink[linkid].point[i].x;
y2 = map[curmap].olink[linkid].point[i].y;
if (isonline(mx,my,x,y,x2,y2)) return TRUE;
x = x2;
y = y2;
}
/* draw line to final map[curmap].object */
x2 = map[curmap].obj[map[curmap].olink[linkid].dstobj].x + map[curmap].olink[linkid].dstxoff;
y2 = map[curmap].obj[map[curmap].olink[linkid].dstobj].y + map[curmap].olink[linkid].dstyoff;
if (isonline(mx,my,x,y,x2,y2)) return TRUE;
return FALSE;
}
int isonlinkdst(int lineid, int x, int y) {
int hx1,hy1,hx2,hy2;
hx1 = map[curmap].obj[map[curmap].olink[lineid].dstobj].x + map[curmap].olink[lineid].dstxoff - (LINESELHANDLESIZE/2);
hy1 = map[curmap].obj[map[curmap].olink[lineid].dstobj].y + map[curmap].olink[lineid].dstyoff - (LINESELHANDLESIZE/2);
hx2 = hx1 + LINESELHANDLESIZE;
hy2 = hy1 + LINESELHANDLESIZE;
if ((x >= hx1) && ( x <= hx2) && (y >= hy1) & (y <= hy2)) {
return TRUE;
}
return FALSE;
}
int isonlinkpoint(int lineid, int mx, int my) {
int i;
for (i = 0; i < map[curmap].olink[lineid].npoints; i++) {
int x,y;
x = map[curmap].olink[lineid].point[i].x;
y = map[curmap].olink[lineid].point[i].y;
if ((mx >= (x-LINESELTHRESHOLD)) && (mx <= (x+LINESELTHRESHOLD)) &&
(my >= (y-LINESELTHRESHOLD)) && (my <= (y+LINESELTHRESHOLD))) {
return i;
}
}
return -1;
}
int isonlinksrc(int lineid, int x, int y) {
int hx1,hy1,hx2,hy2;
hx1 = map[curmap].obj[map[curmap].olink[lineid].srcobj].x + map[curmap].olink[lineid].srcxoff - (LINESELHANDLESIZE/2);
hy1 = map[curmap].obj[map[curmap].olink[lineid].srcobj].y + map[curmap].olink[lineid].srcyoff - (LINESELHANDLESIZE/2);
hx2 = hx1 + LINESELHANDLESIZE;
hy2 = hy1 + LINESELHANDLESIZE;
if ((x >= hx1) && ( x <= hx2) && (y >= hy1) & (y <= hy2)) {
return TRUE;
}
return FALSE;
}
int isonmap(int x, int y) {
if ((x >= 0) && ( y >= 0) && (x <= map[curmap].width) && (y <= map[curmap].height)) {
return TRUE;
}
return FALSE;
}
int isonmapbox(int x, int y) {
if ((x >= mapbox.x) && ( y >= mapbox.y) && (x <= mapbox.x+mapbox.width) && (y <= mapbox.y+mapbox.height)) {
return TRUE;
}
return FALSE;
}
int isonmapboxchildren(int x, int y) {
if ((x >= mapbox.x) && ( y >= mapbox.y+(DEFTEXTH*2)+2) && (x <= mapbox.x+mapbox.width) && (y <= mapbox.y+mapbox.height)) {
return TRUE;
}
return FALSE;
}
int isonmapname(int x, int y) {
if ((x >= mapbox.x) && ( y >= mapbox.y) && (x <= mapbox.x+mapbox.width) && (y <= mapbox.y+DEFTEXTH+2)) {
return TRUE;
}
return FALSE;
}
int isongoback(int x, int y) {
if ((x >= mapbox.x) && ( y >= (mapbox.y + DEFTEXTH))
&& (x <= mapbox.x+mapbox.width) && (y <= mapbox.y+(DEFTEXTH*2))) {
return TRUE;
}
return FALSE;
}
int isonobox(int x, int y) {
if ((x >= obox.x) && ( y >= obox.y) && (x <= obox.x+obox.width) && (y <= obox.y+obox.height)) {
return TRUE;
}
return FALSE;
}
int isontoolbox(int x, int y) {
if ((x >= toolbox.x) && ( y >= toolbox.y) && (x <= toolbox.x+toolbox.width) && (y <= toolbox.y+toolbox.height)) {
return TRUE;
}
return FALSE;
}
void initmap(int mapnum) {
map[mapnum].width = 800;
map[mapnum].height = 600 - DEFTEXTH;
map[mapnum].bpp = 16;
map[mapnum].bgcol.r = 255;
map[mapnum].bgcol.g = 255;
map[mapnum].bgcol.b = 255;
map[mapnum].boxcol.r = 90;
map[mapnum].boxcol.g = 90;
map[mapnum].boxcol.b = 90;
map[mapnum].numthings = 0;
map[mapnum].numobjects = 0;
map[mapnum].numlinks = 0;
map[mapnum].numtext = 0;
map[mapnum].selecteditem = -1;
map[mapnum].selecteditemtype = -1;
map[mapnum].selectedlinkpoint = -1;
map[mapnum].selectedtype = 0;
map[mapnum].curobj = -1; /* map[curmap].object being moved/dragged/etc */
map[mapnum].curlink = -1; /* link being moved/dragged/etc */
map[mapnum].curlinkpoint = -1; /* link pomap[mapnum].being moved/dragged/etc */
map[mapnum].curtext = -1; /* text being moved/dragged/etc */
map[mapnum].startx = -1;
map[mapnum].starty = -1;
map[mapnum].textanchor = -1;
strcpy(map[mapnum].text, "");
if (mapnum == 0) {
sprintf(map[mapnum].name, "Toplevel");
} else {
sprintf(map[mapnum].name, "Map #%d",mapnum);
}
modified = FALSE;
}
void initvars(void) {
nummaps = 1;
strcpy(currentfilename, "");
/* set globals */
initmap(0);
curmap = 0;
obox.x = map[curmap].width + 1;
obox.y = (map[curmap].height / 4) * 3;
obox.width = SIDEBARW;
obox.height = map[curmap].height - obox.y;
obox.pos = 0;
obox.bgcol = black;
obox.gridbgcol = grey4;
obox.gridcol = grey;
obox.gridsize = 30;
obox.gridrowlen = SIDEBARW / obox.gridsize;
toolbox.x = map[curmap].width + 1;
toolbox.y = 0;
toolbox.width = SIDEBARW;
toolbox.height = map[curmap].height / 3;
toolbox.bgcol = black;
//toolbox.gridcol = grey3;
toolbox.gridsize = 30;
toolbox.gridrowlen = SIDEBARW / toolbox.gridsize;
mapbox.x = map[curmap].width + 1;
mapbox.y = toolbox.y+toolbox.height+1;
mapbox.width = SIDEBARW;
mapbox.height = obox.y - mapbox.y - 20;
fgcol = black;
objfillcol = yellow;
}
void raiseselected(void) {
int i;
int temptype,tempid;
int target;
/* find map[curmap].object */
for (i = 0; i < map[curmap].numthings; i++) {
if ((map[curmap].thing[i].id == map[curmap].selecteditem) && (map[curmap].thing[i].type == map[curmap].selecteditemtype)) {
/* swap with one above */
if (i == (map[curmap].numthings-1)) {
break;
} else {
target = i+1;
}
tempid = map[curmap].thing[target].id;
temptype = map[curmap].thing[target].type;
map[curmap].thing[target].id = map[curmap].thing[i].id;
map[curmap].thing[target].type = map[curmap].thing[i].type;
map[curmap].thing[i].id = tempid;
map[curmap].thing[i].type = temptype;
break;
}
}
modified = TRUE;
/* redraw map */
drawmap();
}
int savemap(void) {
char filename[BUFLEN];
FILE *f;
int namelen;
int i;
int eoff;
SDL_Surface *exportmap;
SDL_Rect area;
/* TODO: validate */
strcpy(filename, text);
sprintf(statustext,"Saving map...\n");
drawstatusbar();
/* is this an export? (use extenstion) */
if (strlen(filename) >= 5) {
eoff = strlen(filename)-4;
if ((filename[eoff] == '.') &&
((filename[eoff+1] == 'b') || (filename[eoff+1] == 'B')) &&
((filename[eoff+2] == 'm') || (filename[eoff+2] == 'M')) &&
((filename[eoff+3] == 'p') || (filename[eoff+3] == 'P'))
) {
exportmap = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].width, map[curmap].height,
buffer->format->BitsPerPixel, buffer->format->Rmask,
buffer->format->Gmask,buffer->format->Bmask,
buffer->format->Amask);
state = S_NONE;
drawmap();
area.x = 0;
area.y = 0;
area.w = map[curmap].width;
area.h = map[curmap].height;
SDL_BlitSurface(screen,&area,exportmap, 0);
if (SDL_SaveBMP(exportmap, filename)) {
sprintf(statustext,"ERROR: Could not export to BMP file '%s'.\n",filename);
drawstatusbar();
return TRUE;
}
sprintf(statustext,"Successfully exported map to BMP file '%s'.\n",filename);
drawstatusbar();
return FALSE;
}
}
if ((f = fopen(filename, "wb")) == NULL) {
sprintf(statustext,"ERROR: Could not open '%s'.\n",filename);
drawstatusbar();
return TRUE;
}
/* dump out numbers of map[curmap].objects */
fwrite(&nummaps, sizeof(int), 1, f);
for (i = 0; i < nummaps; i++) {
fwrite(&map[i].width, sizeof(int), 1, f);
fwrite(&map[i].height, sizeof(int), 1, f);
fwrite(&map[i].bpp, sizeof(int), 1, f);
fwrite(&map[i].bgcol, sizeof(SDL_Color), 1, f);
fwrite(&map[i].boxcol, sizeof(SDL_Color), 1, f);
fwrite(&map[i].numthings, sizeof(int), 1, f);
fwrite(&map[i].numobjects, sizeof(int), 1, f);
fwrite(&map[i].numlinks, sizeof(int), 1, f);
fwrite(&map[i].numtext, sizeof(int), 1, f);
/* selecteditem*/
/* selecteditemtype*/
/* selectedlinkpoint*/
/* selectedtype*/
/* curobj*/
/* curlink*/
/* curlinkpoint*/
/* curtext*/
/* startx,starty */
/* textanchor */
/* text*/
namelen = strlen(map[i].name);
fwrite(&namelen, sizeof(int), 1, f);
fwrite(&map[i].name, (namelen+1) * sizeof(char), 1, f);
/* write objects */
fwrite(&map[i].thing, sizeof(thing_t), map[i].numthings, f);
fwrite(&map[i].olink, sizeof(link_t), map[i].numlinks, f);
fwrite(&map[i].obj, sizeof(mapobject_t), map[i].numobjects, f);
fwrite(&map[i].textob, sizeof(text_t), map[i].numtext, f);
}
fclose(f);
modified = FALSE;
sprintf(statustext,"Successfully saved map to '%s'.\n",filename);
/* save filename */
strcpy(currentfilename, filename);
return 0;
}
int showfiledialog(void) {
Uint32 fillcol;
text_t temp;
SDL_Rect area,sarea;
int y;
SDL_Color ccol;
/* clear map */
fillcol = SDL_MapRGB(buffer->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b);
SDL_FillRect(buffer, NULL, fillcol);
/* */
switch (state) {
case S_SAVING:
strcpy(temp.text,"Enter save filename:");
break;
case S_LOADING:
strcpy(temp.text,"Enter load filename:");
break;
case S_MAPNAMING:
strcpy(temp.text,"Enter new map name:");
break;
default:
strcpy(temp.text,"Enter filename:");
break;
}
temp.w = strlen(temp.text) * (DEFTEXTW * 2);
temp.h = DEFTEXTH*2;
temp.x = (map[curmap].width / 2) - (temp.w / 2);
temp.y = (map[curmap].height / 2) - (temp.h*4);
temp.c = black;
temp.anchor = -1;
drawtext(buffer, &temp);
/* draw outlines */
drawbox(buffer,0,0,map[curmap].width-1,map[curmap].height-DEFTEXTH-3,blue);
drawbox(buffer,0,(map[curmap].height/2)-2,map[curmap].width-1,(map[curmap].height/2)+(DEFTEXTH*2)+2,blue);
/* actually draw the text */
/* paste old background */
if (bg != NULL) {
area.x = bgx;
area.y = bgy;
area.w = bg->w;
area.h = bg->h;
SDL_BlitSurface(bg,0,screen, &area);
// free it
//SDL_UpdateRect(screen,area.x, area.y, area.w, area.h);
SDL_FreeSurface(bg);
}
/* copy new background */
sarea.x = startx;
sarea.y = starty;
sarea.w = ((strlen(text)+1) * (DEFTEXTW*2)) +2; // include space for cursor
sarea.h = DEFTEXTH*2;
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,sarea.w, sarea.h,
buffer->format->BitsPerPixel, buffer->format->Rmask,
buffer->format->Gmask,buffer->format->Bmask,
buffer->format->Amask);
SDL_BlitSurface(screen,&sarea,bg,0);
bgx = sarea.x;
bgy = sarea.y;
/* draw text */
strcpy(temp.text, text);
temp.x = startx;
temp.y = starty;
temp.w = strlen(temp.text) * (DEFTEXTW*2);
temp.h = DEFTEXTH*2;
temp.c = fgcol;
temp.anchor = -1;
drawtext(buffer, &temp);
/* draw cursor (a solid block) */
ccol = blue;
for (y = starty ; y < (starty + DEFTEXTH*2); y++ ) {
drawline(buffer, startx + temp.w, y, startx + temp.w + (DEFTEXTW*2),y,ccol);
}
/* blit to screen */
SDL_BlitSurface(buffer, 0, screen, 0);
SDL_UpdateRect(screen, 0, 0, map[curmap].width, map[curmap].height);
return FALSE;
}
int startlink(int x, int y) {
int linex1,liney1,linex2,liney2;
int len;
xoff = x - map[curmap].obj[map[curmap].curobj].x;
yoff = y - map[curmap].obj[map[curmap].curobj].y;
startx = x;
starty = y;
startobj = map[curmap].curobj;
changestate(S_DRAWLINK);
/* copy line */
linex1 = startx;
liney1 = starty;
linex2 = x;
liney2 = y;
len = linelen(linex1,liney1,linex2,liney2);
linebg = malloc((len + 4) * sizeof(int));
copyline(screen, linex1,liney1,linex2,liney2, linebg );
sprintf(statustext,"Creating link #%d...\n", map[curmap].numlinks);
drawstatusbar();
return 0;
}
int startlinkdstmove(int x, int y) {
int linex1,liney1,linex2,liney2;
int len;
startx = x;
starty = y;
changestate(S_LINKDSTMOVE);
/* copy background */
linex1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstxoff;
liney1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstyoff;
linex2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstxoff;
liney2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstyoff;
len = linelen(linex1,liney1,linex2,liney2);
linebg = malloc((len + 4) * sizeof(int));
copyline(screen, linex1,liney1,linex2,liney2, linebg );
sprintf(statustext,"Starting dst endpoint move for link #%d...\n", map[curmap].curlink); fflush(stdout);
drawstatusbar();
return 0;
}
int startlinkpointmove(int x, int y) {
int linex1,liney1,linex2,liney2;
SDL_Rect area;
startx = x;
starty = y;
changestate(S_LINKPOINTMOVE);
/* copy background */
linex1 = map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].x - (LINESELHANDLESIZE / 2);
liney1 = map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].y - (LINESELHANDLESIZE / 2);
linex2 = map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].x + (LINESELHANDLESIZE / 2)+2;
liney2 = map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].y + (LINESELHANDLESIZE / 2)+2;
bg = SDL_CreateRGBSurface(SDL_SWSURFACE, LINESELHANDLESIZE, LINESELHANDLESIZE,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
bgx = linex1;
bgy = liney1;
area.x = linex1;
area.y = liney1;
area.w = LINESELHANDLESIZE+4;
area.h = LINESELHANDLESIZE+4;
SDL_BlitSurface(screen, &area, bg,0);
sprintf(statustext,"Starting link point move for link #%d poinrt #%d...\n", map[curmap].curlink,map[curmap].curlinkpoint);
drawstatusbar();
return 0;
}
int startlinksrcmove(int x, int y) {
int linex1,liney1,linex2,liney2;
int len;
startx = x;
starty = y;
changestate(S_LINKSRCMOVE);
/* copy background */
linex1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcxoff;
liney1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcyoff;
linex2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstxoff;
liney2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstyoff;
len = linelen(linex1,liney1,linex2,liney2);
if (len <= 0) {
printf("ERROR: length is zero or negative - %d\n",len);
fflush(stdout);
exit(1);
}
linebg = malloc((len + 4) * sizeof(int));
if (linebg == NULL) {
printf("ERROR: cannot malloc()\n"); fflush(stdout);
}
copyline(screen, linex1,liney1,linex2,liney2, linebg);
sprintf(statustext,"Starting src endpoint move for link #%d...\n", map[curmap].curlink); fflush(stdout);
drawstatusbar();
return 0;
}
int startlinkmove (int x, int y) {
int linex1,liney1;
int linex2,liney2;
int len;
startx = x;
starty = y;
changestate(S_LINKMOVING);
/* copy background */
linex1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcxoff;
liney1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcyoff;
linex2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].x + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstxoff;
liney2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].y + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstyoff;
len = linelen(linex1,liney1,linex2,liney2);
if (len <= 0) {
printf("ERROR: length is zero or negative - %d\n",len);
fflush(stdout);
exit(1);
}
linebg = malloc((len+4) * sizeof(int));
if (linebg == NULL) {
printf("ERROR: cannot malloc()\n"); fflush(stdout);
}
copyline(screen, linex1,liney1,linex2,liney2, linebg);
sprintf(statustext,"Starting move of link #%d...\n", map[curmap].curlink); fflush(stdout);
drawstatusbar();
return 0;
}
int startobjmove (int x, int y) {
SDL_Rect area;
xoff = map[curmap].obj[map[curmap].curobj].x - x;
yoff = map[curmap].obj[map[curmap].curobj].y - y;
startx = x;
starty = y;
changestate(S_OBJMOVING);
/* copy background */
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].obj[map[curmap].curobj].w,map[curmap].obj[map[curmap].curobj].h,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
area.x = map[curmap].obj[map[curmap].curobj].x;
area.y = map[curmap].obj[map[curmap].curobj].y;
area.w = map[curmap].obj[map[curmap].curobj].w;
area.h = map[curmap].obj[map[curmap].curobj].h;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
return 0;
}
int startresize (int x, int y) {
SDL_Rect area;
startx = x;
starty = y;
changestate(S_RESIZING);
/* copy background */
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,MAXOBJWIDTH+2,MAXOBJHEIGHT+2,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
area.x = map[curmap].obj[map[curmap].curobj].x;
area.y = map[curmap].obj[map[curmap].curobj].y;
area.w = map[curmap].obj[map[curmap].curobj].w+2;
area.h = map[curmap].obj[map[curmap].curobj].h+2;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
return 0;
}
int startresizetext(int x, int y) {
SDL_Rect area;
int txoff,tyoff;
if (map[curmap].textob[map[curmap].curtext].anchor == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].x;
tyoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].y;
}
startx = x;
starty = y;
changestate(S_TEXTRESIZING);
/* copy background */
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].width,map[curmap].height,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
area.x = map[curmap].textob[map[curmap].curtext].x + txoff;
area.y = map[curmap].textob[map[curmap].curtext].y + tyoff;
area.w = map[curmap].textob[map[curmap].curtext].w+2;
area.h = map[curmap].textob[map[curmap].curtext].h+2;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
return 0;
}
int starttextmove (int x, int y) {
SDL_Rect area;
int txoff,tyoff;
if (map[curmap].textob[map[curmap].curtext].anchor == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].x;
tyoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].y;
}
xoff = map[curmap].textob[map[curmap].curtext].x - x + txoff;
yoff = map[curmap].textob[map[curmap].curtext].y - y + tyoff;
startx = x ;
starty = y ;
changestate(S_TEXTMOVING);
/* copy background */
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].textob[map[curmap].curtext].w,map[curmap].textob[map[curmap].curtext].h,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
area.x = map[curmap].textob[map[curmap].curtext].x + txoff;
area.y = map[curmap].textob[map[curmap].curtext].y + tyoff;
area.w = map[curmap].textob[map[curmap].curtext].w;
area.h = map[curmap].textob[map[curmap].curtext].h;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
return 0;
}
int textat(int x, int y) {
int i,anchor;
for (i = 0; i < map[curmap].numtext; i++) {
anchor = map[curmap].textob[i].anchor;
if (anchor == -1) {
if ( (x >= map[curmap].textob[i].x ) && (x <= (map[curmap].textob[i].x + map[curmap].textob[i].w)) &&
(y >= map[curmap].textob[i].y ) && (y <= (map[curmap].textob[i].y + map[curmap].textob[i].h)) ) {
return i;
}
} else {
if ( (x >= map[curmap].textob[i].x + map[curmap].obj[anchor].x ) && (x <= (map[curmap].textob[i].x + map[curmap].obj[anchor].x + map[curmap].textob[i].w)) &&
(y >= map[curmap].textob[i].y + map[curmap].obj[anchor].y ) && (y <= (map[curmap].textob[i].y + map[curmap].obj[anchor].y + map[curmap].textob[i].h)) ) {
return i;
}
}
}
return -1;
}
int thingat(int x, int y) {
int i;
int anchor;
for (i = (map[curmap].numthings-1); i >= 0; i--) {
switch (map[curmap].thing[i].type) {
case T_OBJECT:
if ( (x >= map[curmap].obj[map[curmap].thing[i].id].x ) &&
(x <= (map[curmap].obj[map[curmap].thing[i].id].x + map[curmap].obj[map[curmap].thing[i].id].w)) &&
(y >= map[curmap].obj[map[curmap].thing[i].id].y ) &&
(y <= (map[curmap].obj[map[curmap].thing[i].id].y + map[curmap].obj[map[curmap].thing[i].id].h)) ) {
return i;
}
break;
case T_LINK:
if (isonlink(map[curmap].thing[i].id, x, y)) {
return i;
}
break;
case T_TEXT:
anchor = map[curmap].textob[map[curmap].thing[i].id].anchor;
if (anchor == -1) {
if ( (x >= map[curmap].textob[map[curmap].thing[i].id].x ) && (x <= (map[curmap].textob[map[curmap].thing[i].id].x + map[curmap].textob[map[curmap].thing[i].id].w)) &&
(y >= map[curmap].textob[map[curmap].thing[i].id].y ) && (y <= (map[curmap].textob[map[curmap].thing[i].id].y + map[curmap].textob[map[curmap].thing[i].id].h)) ) {
return i;
}
} else {
if ( (x >= map[curmap].textob[map[curmap].thing[i].id].x + map[curmap].obj[anchor].x ) && (x <= (map[curmap].textob[map[curmap].thing[i].id].x + map[curmap].obj[anchor].x + map[curmap].textob[map[curmap].thing[i].id].w)) &&
(y >= map[curmap].textob[map[curmap].thing[i].id].y + map[curmap].obj[anchor].y ) && (y <= (map[curmap].textob[map[curmap].thing[i].id].y + map[curmap].obj[anchor].y + map[curmap].textob[map[curmap].thing[i].id].h)) ) {
return i;
}
}
break;
}
}
return -1;
}
int updatefilename(void) {
int y;
SDL_Rect sarea;
SDL_Rect area;
SDL_Color ccol = blue;
text_t temp;
/* paste old background */
if (bg != NULL) {
area.x = bgx;
area.y = bgy;
area.w = bg->w;
area.h = bg->h;
SDL_BlitSurface(bg,0,screen, &area);
SDL_UpdateRect(screen, bgx, bgy, bg->w, bg->h);
// free it
SDL_FreeSurface(bg);
}
/* copy new background */
sarea.x = startx;
sarea.y = starty;
sarea.w = ((strlen(text)+1) * (DEFTEXTW*2)) +2; // include space for cursor
sarea.h = DEFTEXTH*2;
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,sarea.w, sarea.h,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
SDL_BlitSurface(screen,&sarea,bg,0);
bgx = sarea.x;
bgy = sarea.y;
/* draw text */
strcpy(temp.text, text);
temp.x = startx;
temp.y = starty;
temp.w = strlen(text) * (DEFTEXTW*2);
temp.h = DEFTEXTH*2;
temp.c = black;
temp.anchor = -1;
drawtext(screen, &temp);
/* draw cursor (a solid block) */
for (y = starty ; y < (starty + (DEFTEXTH*2)); y++ ) {
drawline(screen, startx + temp.w, y, startx + temp.w + DEFTEXTW*2,y,ccol);
}
SDL_UpdateRect(screen, startx, starty, temp.w + DEFTEXTW*2, DEFTEXTH*2);
return FALSE;
}
int updatelinkshadow(int x, int y) {
int len;
int w,h;
int tlx,tly;
int linex1,liney1,linex2,liney2;
/* replace old bg */
pasteline(screen,linebg);
/* copy current bg */
linex1 = startx;
liney1 = starty;
linex2 = x;
liney2 = y;
len = linelen(linex1,liney1,linex2,liney2);
linebg = malloc((len + 4) * sizeof(int));
copyline(screen, linex1,liney1,linex2,liney2, linebg);
/* draw line */
drawline(screen,startx,starty,x,y, map[curmap].boxcol);
if (x < startx) {
if (y < starty) {
tlx = x;
tly = y;
w = startx - x;
h = starty - y;
} else {
tlx = x;
tly = starty;
w = startx - x;
h = y - starty;
}
} else {
if (y < starty) {
tlx = startx;
tly = y;
w = x - startx;
h = starty - y;
} else {
tlx = startx;
tly = starty;
w = x - startx;
h = y - starty;
}
}
SDL_UpdateRect(screen, tlx, tly,w,h);
return 0;
}
int updatelinkpointshadow(int x, int y) {
int linex1,liney1,linex2,liney2;
SDL_Rect area;
int ty;
/* paste old bg */
area.x = bgx;
area.y = bgy;
area.w = bg->w;
area.h = bg->h;
SDL_BlitSurface(bg, 0, screen, &area);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* copy background */
linex1 = x - (LINESELHANDLESIZE / 2);
liney1 = y - (LINESELHANDLESIZE / 2);
linex2 = x + (LINESELHANDLESIZE / 2)+4;
liney2 = y + (LINESELHANDLESIZE / 2)+4;
bg = SDL_CreateRGBSurface(SDL_SWSURFACE, LINESELHANDLESIZE, LINESELHANDLESIZE,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
bgx = linex1;
bgy = liney1;
bgw = LINESELHANDLESIZE+4;
bgh = LINESELHANDLESIZE+4;
area.x = linex1;
area.y = liney1;
area.w = LINESELHANDLESIZE;
area.h = LINESELHANDLESIZE;
SDL_BlitSurface(screen, &area, bg,0);
/* draw link point */
for (ty = liney1; ty < (liney1+LINESELHANDLESIZE-1); ty++) {
drawline(screen, linex1, ty, linex1+LINESELHANDLESIZE-1, ty, black);
}
//SDL_UpdateRect(screen, linex1, liney1, linex2, liney2);
SDL_Flip(screen);
return FALSE;
}
int updatemoveshadow(int x, int y) {
SDL_Rect area;
if ((x + xoff) < 0) xoff = -x;
if ((y + yoff) < 0) yoff = -y;
x += xoff;
y += yoff;
/* replace old bg */
area.x = bgx;
area.y = bgy;
area.w = bgw;
area.h = bgh;
SDL_BlitSurface(bg, 0, screen, &area);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* copy current bg */
area.x = x;
area.y = y;
area.w = map[curmap].obj[map[curmap].curobj].w;
area.h = map[curmap].obj[map[curmap].curobj].h;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
/* draw box */
if ((x > 0) && (y > 0) && (x+map[curmap].obj[map[curmap].curobj].w-1 < map[curmap].width) && (y+map[curmap].obj[map[curmap].curobj].h-1 < map[curmap].height)) {
drawline(screen,x,y,x+map[curmap].obj[map[curmap].curobj].w-1,y, map[curmap].boxcol);
drawline(screen,x,y,x,y+map[curmap].obj[map[curmap].curobj].h-1, map[curmap].boxcol);
drawline(screen,x,y+map[curmap].obj[map[curmap].curobj].h-1,x+map[curmap].obj[map[curmap].curobj].w-1,y+map[curmap].obj[map[curmap].curobj].h-1, map[curmap].boxcol);
drawline(screen,x+map[curmap].obj[map[curmap].curobj].w-1,y,x+map[curmap].obj[map[curmap].curobj].w-1,y+map[curmap].obj[map[curmap].curobj].h-1, map[curmap].boxcol);
}
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
return 0;
}
int updateresizeshadow(int x, int y) {
SDL_Rect sarea;
SDL_Rect area;
int xdiff,ydiff;
xdiff = x - startx;
ydiff = y - starty;
/* check for maximum object sizes */
if ((map[curmap].obj[map[curmap].curobj].w + xdiff) > MAXOBJWIDTH) xdiff = MAXOBJWIDTH - map[curmap].obj[map[curmap].curobj].w;
if ((map[curmap].obj[map[curmap].curobj].h + ydiff) > MAXOBJHEIGHT) ydiff = MAXOBJHEIGHT - map[curmap].obj[map[curmap].curobj].h;
if ((map[curmap].obj[map[curmap].curobj].w + xdiff) < MINOBJWIDTH) xdiff = MINOBJWIDTH - map[curmap].obj[map[curmap].curobj].w ;
if ((map[curmap].obj[map[curmap].curobj].h + ydiff) < MINOBJHEIGHT) ydiff = MINOBJHEIGHT - map[curmap].obj[map[curmap].curobj].h ;
/* check for edges of screen */
if ((map[curmap].obj[map[curmap].curobj].x + map[curmap].obj[map[curmap].curobj].w + xdiff) >= map[curmap].width) {
xdiff = 0;
}
if ((map[curmap].obj[map[curmap].curobj].y + map[curmap].obj[map[curmap].curobj].h + ydiff) >= map[curmap].height) {
ydiff = 0;
//ydiff = (map[curmap].height - map[curmap].obj[map[curmap].curobj].h);
}
/* replace old bg */
area.x = bgx;
area.y = bgy;
area.w = bgw;
area.h = bgh;
sarea.x = 0;
sarea.y = 0;
sarea.w = bgw;
sarea.h = bgh;
SDL_BlitSurface(bg, &sarea, screen, &area);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* copy current bg */
area.x = map[curmap].obj[map[curmap].curobj].x;
area.y = map[curmap].obj[map[curmap].curobj].y;
area.w = map[curmap].obj[map[curmap].curobj].w + xdiff + 2;
area.h = map[curmap].obj[map[curmap].curobj].h + ydiff + 2;
if (area.w < MINOBJWIDTH) area.w = MINOBJWIDTH;
if (area.h < MINOBJHEIGHT) area.h = MINOBJHEIGHT;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
/* draw box */
drawline(screen,map[curmap].obj[map[curmap].curobj].x, map[curmap].obj[map[curmap].curobj].y,
map[curmap].obj[map[curmap].curobj].x+map[curmap].obj[map[curmap].curobj].w+xdiff, map[curmap].obj[map[curmap].curobj].y , map[curmap].boxcol);
drawline(screen,map[curmap].obj[map[curmap].curobj].x, map[curmap].obj[map[curmap].curobj].y,
map[curmap].obj[map[curmap].curobj].x, map[curmap].obj[map[curmap].curobj].y+map[curmap].obj[map[curmap].curobj].h+ydiff , map[curmap].boxcol);
drawline(screen,map[curmap].obj[map[curmap].curobj].x+map[curmap].obj[map[curmap].curobj].w+xdiff, map[curmap].obj[map[curmap].curobj].y,
map[curmap].obj[map[curmap].curobj].x+map[curmap].obj[map[curmap].curobj].w+xdiff, map[curmap].obj[map[curmap].curobj].y+map[curmap].obj[map[curmap].curobj].h+ydiff , map[curmap].boxcol);
drawline(screen,map[curmap].obj[map[curmap].curobj].x, map[curmap].obj[map[curmap].curobj].y+map[curmap].obj[map[curmap].curobj].h+ydiff,
map[curmap].obj[map[curmap].curobj].x+map[curmap].obj[map[curmap].curobj].w+xdiff, map[curmap].obj[map[curmap].curobj].y+map[curmap].obj[map[curmap].curobj].h+ydiff , map[curmap].boxcol);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
return 0;
}
int updateresizetextshadow(int x, int y) {
SDL_Rect sarea;
SDL_Rect area;
int xdiff,ydiff;
int txoff,tyoff;
if (map[curmap].textob[map[curmap].curtext].anchor == -1) {
txoff = 0;
tyoff = 0;
} else {
txoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].x;
tyoff = map[curmap].obj[map[curmap].textob[map[curmap].curtext].anchor].y;
}
xdiff = x - startx;
ydiff = y - starty;
if ((map[curmap].textob[map[curmap].curtext].w + xdiff) > strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH) xdiff = (strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH)-map[curmap].textob[map[curmap].curtext].w;
if ((map[curmap].textob[map[curmap].curtext].h + ydiff) > MAXLETTERHEIGHT) ydiff = MAXLETTERHEIGHT - map[curmap].textob[map[curmap].curtext].h;
if ((map[curmap].textob[map[curmap].curtext].w + xdiff) < strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH)
xdiff = (strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH) - map[curmap].textob[map[curmap].curtext].w ;
if ((map[curmap].textob[map[curmap].curtext].h + ydiff) < MINLETTERHEIGHT) ydiff = MINLETTERHEIGHT - map[curmap].textob[map[curmap].curtext].h ;
/* replace old bg */
area.x = bgx;
area.y = bgy;
area.w = bgw;
area.h = bgh;
sarea.x = 0;
sarea.y = 0;
sarea.w = bgw;
sarea.h = bgh;
SDL_BlitSurface(bg, &sarea, screen, &area);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* copy current bg */
area.x = map[curmap].textob[map[curmap].curtext].x + txoff;
area.y = map[curmap].textob[map[curmap].curtext].y + tyoff;
area.w = map[curmap].textob[map[curmap].curtext].w + xdiff + 2;
area.h = map[curmap].textob[map[curmap].curtext].h + ydiff + 2;
if (area.w < strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH) area.w = strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH;
if (area.h < MINLETTERHEIGHT) area.h = MINLETTERHEIGHT;
if (area.w > strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH ) area.w = strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH;
if (area.h > MAXLETTERHEIGHT) area.h = MAXLETTERHEIGHT;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
/* draw box */
drawline(screen,map[curmap].textob[map[curmap].curtext].x+txoff, map[curmap].textob[map[curmap].curtext].y+tyoff,
map[curmap].textob[map[curmap].curtext].x+txoff+map[curmap].textob[map[curmap].curtext].w+xdiff, map[curmap].textob[map[curmap].curtext].y+tyoff , map[curmap].boxcol);
drawline(screen,map[curmap].textob[map[curmap].curtext].x+txoff, map[curmap].textob[map[curmap].curtext].y+tyoff,
map[curmap].textob[map[curmap].curtext].x+txoff, map[curmap].textob[map[curmap].curtext].y+tyoff+map[curmap].textob[map[curmap].curtext].h+ydiff , map[curmap].boxcol);
drawline(screen,map[curmap].textob[map[curmap].curtext].x+txoff+map[curmap].textob[map[curmap].curtext].w+xdiff, map[curmap].textob[map[curmap].curtext].y+tyoff,
map[curmap].textob[map[curmap].curtext].x+txoff+map[curmap].textob[map[curmap].curtext].w+xdiff, map[curmap].textob[map[curmap].curtext].y+tyoff+map[curmap].textob[map[curmap].curtext].h+ydiff , map[curmap].boxcol);
drawline(screen,map[curmap].textob[map[curmap].curtext].x+txoff, map[curmap].textob[map[curmap].curtext].y+tyoff+map[curmap].textob[map[curmap].curtext].h+ydiff,
map[curmap].textob[map[curmap].curtext].x+txoff+map[curmap].textob[map[curmap].curtext].w+xdiff, map[curmap].textob[map[curmap].curtext].y+tyoff+map[curmap].textob[map[curmap].curtext].h+ydiff , map[curmap].boxcol);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
return 0;
}
int updatetextcursor(void) {
int y;
SDL_Rect sarea;
SDL_Rect area;
SDL_Color ccol = blue;
text_t temp;
if ((state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING)) {
showfiledialog();
return 0;
}
/* paste old background */
if (bg != NULL) {
area.x = bgx;
area.y = bgy;
area.w = bg->w;
area.h = bg->h;
SDL_BlitSurface(bg,0,screen, &area);
SDL_UpdateRect(screen, bgx, bgy, bg->w, bg->h);
// free it
SDL_FreeSurface(bg);
}
/* copy new background */
sarea.x = startx;
sarea.y = starty;
sarea.w = ((strlen(text)+1) * (DEFTEXTW)) +2; // include space for cursor
sarea.h = DEFTEXTH;
bg = SDL_CreateRGBSurface(SDL_SWSURFACE,sarea.w, sarea.h,
screen->format->BitsPerPixel, screen->format->Rmask,
screen->format->Gmask,screen->format->Bmask,
screen->format->Amask);
SDL_BlitSurface(screen,&sarea,bg,0);
bgx = sarea.x;
bgy = sarea.y;
/* draw text */
strcpy(temp.text, text);
temp.x = startx;
temp.y = starty;
temp.w = strlen(text) * (DEFTEXTW);
temp.h = DEFTEXTH;
temp.c = fgcol;
temp.anchor = -1;
drawtext(screen, &temp);
/* draw cursor (a solid block) */
for (y = starty ; y < (starty + DEFTEXTH); y++ ) {
drawline(screen, startx + temp.w, y, startx + temp.w + DEFTEXTW,y,ccol);
}
SDL_UpdateRect(screen, startx, starty, temp.w + DEFTEXTW, DEFTEXTH);
return FALSE;
}
int endlink(int x, int y) {
int endxoff,endyoff;
int i;
/* replace old bg */
pasteline(screen,linebg);
/* check if we've exceeded the max number of links */
if ((map[curmap].numlinks+1) >= MAXLINKS) {
sprintf(statustext,"ERROR: Maximum link count (%d) exceeded.", MAXLINKS);
return TRUE;
}
/*
endxoff = x - map[curmap].obj[endobj].x;
endyoff = y - map[curmap].obj[endobj].y;
*/
/* centre offsets*/
xoff = (map[curmap].obj[startobj].w / 2);
yoff = (map[curmap].obj[startobj].h / 2);
endxoff = (map[curmap].obj[endobj].w / 2);
endyoff = (map[curmap].obj[endobj].h / 2);
map[curmap].olink[map[curmap].numlinks].srcobj = startobj;
map[curmap].olink[map[curmap].numlinks].srcxoff = xoff;
map[curmap].olink[map[curmap].numlinks].srcyoff = yoff;
map[curmap].olink[map[curmap].numlinks].dstobj = endobj;
map[curmap].olink[map[curmap].numlinks].dstxoff = endxoff;
map[curmap].olink[map[curmap].numlinks].dstyoff = endyoff;
map[curmap].olink[map[curmap].numlinks].col = fgcol;
map[curmap].olink[map[curmap].numlinks].style = LS_NORMAL;
map[curmap].olink[map[curmap].numlinks].npoints = 0;
/* add to 'thing' list */
/* links start at the bottom of the thing list */
/* shuffle all things up */
for (i = (map[curmap].numthings-1); i >= 0 ; i--) {
map[curmap].thing[i+1].type = map[curmap].thing[i].type;
map[curmap].thing[i+1].id = map[curmap].thing[i].id;
}
map[curmap].thing[0].type = T_LINK;
map[curmap].thing[0].id = map[curmap].numlinks;
modified = TRUE;
sprintf(statustext,"Link #%d created (from obj #%d to obj #%d).\n", map[curmap].numlinks, startobj, endobj);
map[curmap].numlinks++;
map[curmap].numthings++;
drawstatusbar();
return 0;
}
int endlinkdstmove(int x, int y) {
int o;
/* free variable */
if (linebg) free(linebg);
/* find which map[curmap].object it's over */
o = objat(x, y);
if (o == -1) {
/* if it's not over an map[curmap].object, abort the move */
changestate(S_NONE);
map[curmap].curlink = -1;
sprintf(statustext,"Move of link #%d dst endpoint aborted.\n",map[curmap].curlink);
} else if (o == map[curmap].olink[map[curmap].curlink].dstobj) {
/* if over the same map[curmap].object, update offsets */
map[curmap].olink[map[curmap].curlink].dstxoff = x - map[curmap].obj[o].x;
map[curmap].olink[map[curmap].curlink].dstyoff = y - map[curmap].obj[o].y;
modified = TRUE;
sprintf(statustext,"Link #%d dst endpoint moved to offset (+%d,+%d).\n",map[curmap].curlink, map[curmap].olink[map[curmap].curlink].dstxoff,map[curmap].olink[map[curmap].curlink].dstyoff);
} else {
/* else if over a new map[curmap].object, update map[curmap].objid and offsets */
map[curmap].olink[map[curmap].curlink].dstobj = o;
map[curmap].olink[map[curmap].curlink].dstxoff = x - map[curmap].obj[o].x;
map[curmap].olink[map[curmap].curlink].dstyoff = y - map[curmap].obj[o].y;
modified = TRUE;
sprintf(statustext,"Link #%d dst endpoint moved to object %d(+%d,+%d).\n",map[curmap].curlink,o, map[curmap].olink[map[curmap].curlink].dstxoff,map[curmap].olink[map[curmap].curlink].dstyoff);
}
drawstatusbar();
return 0;
}
int endlinkpointmove(int x, int y) {
/* free variable */
if (bg) free(bg);
map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].x = x;
map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].y = y;
modified = TRUE;
sprintf(statustext,"Link #%d point #%d moved to (%d,%d).\n",map[curmap].curlink, map[curmap].curlinkpoint, map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].x,map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].y);
drawstatusbar();
return 0;
}
int endlinksrcmove(int x, int y) {
int o;
/* free variable */
if (linebg) free(linebg);
/* find which map[curmap].object it's over */
o = objat(x, y);
if (o == -1) {
/* if it's not over an map[curmap].object, abort the move */
changestate(S_NONE);
map[curmap].curlink = -1;
sprintf(statustext,"Move of link #%d src endpoint aborted.\n",map[curmap].curlink);
} else if (o == map[curmap].olink[map[curmap].curlink].srcobj) {
/* if over the same map[curmap].object, update offsets */
map[curmap].olink[map[curmap].curlink].srcxoff = x - map[curmap].obj[o].x;
map[curmap].olink[map[curmap].curlink].srcyoff = y - map[curmap].obj[o].y;
modified = TRUE;
sprintf(statustext,"Link #%d src endpoint moved to offset (+%d,+%d).\n",map[curmap].curlink, map[curmap].olink[map[curmap].curlink].srcxoff,map[curmap].olink[map[curmap].curlink].srcyoff);
} else {
/* else if over a new map[curmap].object, update map[curmap].objid and offsets */
map[curmap].olink[map[curmap].curlink].srcobj = o;
map[curmap].olink[map[curmap].curlink].srcxoff = x - map[curmap].obj[o].x;
map[curmap].olink[map[curmap].curlink].srcyoff = y - map[curmap].obj[o].y;
modified = TRUE;
sprintf(statustext,"Link #%d src endpoint moved to object %d(+%d,+%d).\n",map[curmap].curlink,o, map[curmap].olink[map[curmap].curlink].srcxoff,map[curmap].olink[map[curmap].curlink].srcyoff);
}
drawstatusbar();
return 0;
}
int endlinkmove(int x, int y) {
/* free variable */
//printf("about to free linebg (0x%x)\n",linebg); fflush(stdout);
if (linebg) free(linebg);
modified = TRUE;
/* TODO: move the line */
return 0;
}
void drillto(int mapnum) {
if (mapnum == -1) {
if (nummaps < (MAXMAPS-1)) {
/* push current map */
history[numhistory] = curmap;
numhistory++;
/* change child */
map[curmap].obj[map[curmap].selecteditem].child = nummaps;
/* create a new map */
initmap(nummaps);
/* select the new map */
curmap = nummaps;
nummaps++;
sprintf(statustext,"Drilled down (new map created).");
startx = 1;
starty = (map[curmap].height/2)-2;
bg = NULL;
strcpy(text, map[curmap].name);
changestate(S_MAPNAMING);
drawmap();
} else {
sprintf(statustext, "ERROR: Maximum number of maps reached.");
drawstatusbar();
}
} else {
/* push current map */
history[numhistory] = curmap;
numhistory++;
curmap = mapnum;
sprintf(statustext,"Drilled down into map #%d (%s).",curmap,map[curmap].name);
drawmap();
}
}
int endobjmove(int x, int y) {
SDL_FreeSurface(bg);
/* check position */
if ((map[curmap].obj[map[curmap].curobj].x + x - startx) >= (map[curmap].width - map[curmap].obj[map[curmap].curobj].w)) {
return -1;
}
if ((map[curmap].obj[map[curmap].curobj].y + y - starty) >= (map[curmap].height - map[curmap].obj[map[curmap].curobj].h)) {
return -1;
}
if (map[curmap].obj[map[curmap].curobj].y + y - starty <= 0) {
return -1;
}
if (map[curmap].obj[map[curmap].curobj].x + x - startx <= 0) {
return -1;
}
modified = TRUE;
map[curmap].obj[map[curmap].curobj].x += (x - startx);
map[curmap].obj[map[curmap].curobj].y += (y - starty);
return 0;
}
int endresize(int x, int y) {
int origw,origh;
int neww,newh;
int i;
float xscale,yscale;
SDL_FreeSurface(bg);
origw = map[curmap].obj[map[curmap].curobj].w;
origh = map[curmap].obj[map[curmap].curobj].h;
neww = map[curmap].obj[map[curmap].curobj].w;
newh = map[curmap].obj[map[curmap].curobj].h;
if (map[curmap].obj[map[curmap].curobj].w + (x - startx) > 0) {
neww = map[curmap].obj[map[curmap].curobj].w + (x - startx);
}
if (map[curmap].obj[map[curmap].curobj].h + (y - starty) > 0) {
newh = map[curmap].obj[map[curmap].curobj].h + (y - starty);
}
if (neww < MINOBJWIDTH) neww = MINOBJWIDTH;
if (newh < MINOBJHEIGHT) newh = MINOBJHEIGHT;
if (neww > MAXOBJWIDTH) neww = MAXOBJWIDTH;
if (newh > MAXOBJHEIGHT) newh = MAXOBJHEIGHT;
if (map[curmap].obj[map[curmap].curobj].x + neww >= map[curmap].width) {
neww = map[curmap].width - map[curmap].obj[map[curmap].curobj].x-1;
}
if (map[curmap].obj[map[curmap].curobj].y + newh >= map[curmap].height) {
newh = map[curmap].height - map[curmap].obj[map[curmap].curobj].y-1;
}
map[curmap].obj[map[curmap].curobj].w = neww;
map[curmap].obj[map[curmap].curobj].h = newh;
/* update default map[curmap].object size */
objtype[map[curmap].obj[map[curmap].curobj].type].defw = neww;
objtype[map[curmap].obj[map[curmap].curobj].type].defh = newh;
/* scale all link endpoints in this map[curmap].object */
xscale = (float)neww / (float)origw;
yscale = (float)newh / (float)origh;
for (i = 0; i < map[curmap].numlinks; i++) {
if (map[curmap].olink[i].srcobj == map[curmap].curobj) {
map[curmap].olink[i].srcxoff = map[curmap].olink[i].srcxoff * xscale;
map[curmap].olink[i].srcyoff = map[curmap].olink[i].srcyoff * yscale;
}
if (map[curmap].olink[i].dstobj == map[curmap].curobj) {
map[curmap].olink[i].dstxoff = map[curmap].olink[i].dstxoff * xscale;
map[curmap].olink[i].dstyoff = map[curmap].olink[i].dstyoff * yscale;
}
}
/* scale x,y of any text anchored to this map[curmap].object */
for (i = 0; i < map[curmap].numtext; i++) {
if (map[curmap].textob[i].anchor == map[curmap].curobj) {
map[curmap].textob[i].x = map[curmap].textob[i].x * xscale;
map[curmap].textob[i].y = map[curmap].textob[i].y * yscale;
}
}
modified = TRUE;
drawmap();
return 0;
}
int endtextresize(int x, int y) {
int origw,origh;
int neww,newh;
SDL_FreeSurface(bg);
origw = map[curmap].textob[map[curmap].curtext].w;
origh = map[curmap].textob[map[curmap].curtext].h;
neww = map[curmap].textob[map[curmap].curtext].w;
newh = map[curmap].textob[map[curmap].curtext].h;
if (map[curmap].textob[map[curmap].curtext].w + (x - startx) > 0) {
neww = map[curmap].textob[map[curmap].curtext].w + (x - startx);
}
if (map[curmap].textob[map[curmap].curtext].h + (y - starty) > 0) {
newh = map[curmap].textob[map[curmap].curtext].h + (y - starty);
}
if (neww < strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH) neww = strlen(map[curmap].textob[map[curmap].curtext].text) * MINLETTERWIDTH;
if (newh < MINLETTERHEIGHT) newh = MINLETTERHEIGHT;
if (neww > strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH ) neww = strlen(map[curmap].textob[map[curmap].curtext].text) * MAXLETTERWIDTH;
if ((map[curmap].textob[map[curmap].curtext].x + neww) >= map[curmap].width ) neww = map[curmap].width - map[curmap].textob[map[curmap].curtext].x - 1;
if (newh > MAXLETTERHEIGHT) newh = MAXLETTERHEIGHT;
if ((map[curmap].textob[map[curmap].curtext].y + newh) >= map[curmap].height ) newh = map[curmap].height - map[curmap].textob[map[curmap].curtext].y - 1;
map[curmap].textob[map[curmap].curtext].w = neww;
map[curmap].textob[map[curmap].curtext].h = newh;
/* update default text size */
/* TODO: is this useful? */
/*
objtype[map[curmap].obj[map[curmap].curobj].type].defw = neww;
objtype[map[curmap].obj[map[curmap].curobj].type].defh = newh;
*/
modified = TRUE;
drawmap();
return 0;
}
int updatetextshadow(int x, int y) {
SDL_Rect area;
x += xoff;
y += yoff;
if (x < 0) x = 0;
if (y < 0) y = 0;
/* replace old bg */
area.x = bgx;
area.y = bgy;
area.w = bgw;
area.h = bgh;
SDL_BlitSurface(bg, 0, screen, &area);
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
/* copy current bg */
area.x = x;
area.y = y;
area.w = map[curmap].textob[map[curmap].curtext].w;
area.h = map[curmap].textob[map[curmap].curtext].h;
SDL_BlitSurface(screen,&area,bg,0);
bgx = area.x;
bgy = area.y;
bgw = area.w;
bgh = area.h;
/* draw box */
if ((x > 0) && (y > 0) && (x+map[curmap].textob[map[curmap].curtext].w-1 < map[curmap].width) && (y+map[curmap].textob[map[curmap].curtext].h-1 < map[curmap].height)) {
drawline(screen,x,y,x+map[curmap].textob[map[curmap].curtext].w-1,y, map[curmap].boxcol);
drawline(screen,x,y,x,y+map[curmap].textob[map[curmap].curtext].h-1, map[curmap].boxcol);
drawline(screen,x,y+map[curmap].textob[map[curmap].curtext].h-1,x+map[curmap].textob[map[curmap].curtext].w-1,y+map[curmap].textob[map[curmap].curtext].h-1, map[curmap].boxcol);
drawline(screen,x+map[curmap].textob[map[curmap].curtext].w-1,y,x+map[curmap].textob[map[curmap].curtext].w-1,y+map[curmap].textob[map[curmap].curtext].h-1, map[curmap].boxcol);
}
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
return 0;
}