#include #include #include #include #include #include #include #include #include #include #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; }