#include #include #include #include #include #include #include #include #include #include #include #include #include "savepng.h" #include "netmapr.h" #include "constants.h" SDL_Surface *screen, *buffer; SDL_Surface *emptyimg; SDL_Surface *icon; SDL_Event event; int isevent; char svgbuf[BUFLEN]; FILE *svgfile; TTF_Font *font[MAXLETTERHEIGHT]; SDL_Color white = { 255, 255, 255, USECOLOUR}; SDL_Color black = { 0, 0, 0, USECOLOUR}; SDL_Color red = { 255, 0, 0, USECOLOUR}; SDL_Color green = { 0, 255, 0, USECOLOUR}; SDL_Color blue = { 0, 0, 255, USECOLOUR}; SDL_Color blue2 = { 0, 0, 70, USECOLOUR}; SDL_Color yellow = { 255, 255, 0, USECOLOUR}; SDL_Color cyan = { 0, 255, 255, USECOLOUR}; SDL_Color purple = { 255, 0, 255, USECOLOUR}; SDL_Color grey = { 90, 90, 90, USECOLOUR}; SDL_Color grey2 = { 70, 70, 70, USECOLOUR}; SDL_Color grey3 = { 50, 50, 50, USECOLOUR}; SDL_Color grey4 = { 30, 30, 30, USECOLOUR}; SDL_Color statusbarcolour = { 255, 255, 255, 0 }; SDL_Surface *searchbg; int searchflash = 0; int searchcounter = 0; int searchticks = 0; int oldsearchticks = 0; int errorflash = 0; int errorcounter = 0; int errorticks = 0; int olderrorticks = 0; int infoflash = 0; int infocounter = 0; int infoticks = 0; int oldinfoticks = 0; SDL_Color gridhigh = {255, 255, 255, 0}; SDL_Color gridmiddle = {90, 90, 90, 0}; SDL_Color gridlow = {50, 50, 50, 0}; SDL_Cursor *normalmouse; SDL_Cursor *objmouse; SDL_Cursor *textmouse; int linemask[MAXLINESTYLE][LINESTYLESIZE]; xy_t fillstack[MAXFILLSTACK]; int fillstackptr = 0; /* screen "viewpane" position */ int screenx = 0; int screeny = 0; int thingdrawn[MAXOBJECTS + MAXLINKS]; SDL_Color fgcol; SDL_Color objfillcol; Uint8 defthickness = 1; Uint8 defstyle = LS_SOLID; Uint8 defarrow = 0; int modified = FALSE; int readonly = FALSE; int needtocalc = FALSE; int maplistpos = 0; /* scroll position in map list */ int copyfrom = -1; int copymap = -1; int copytype = T_MAP; int searchmap = 0; int searchtob = 0; int searchwrap = FALSE; char searchtext[BUFLEN]; int grid = TRUE; int gridsize = 15; int gridsizelist[] = {0, 10, 15, 20}; int gridsizeindex = 1; int gridsizenum = 4; SDL_Color gridcol = {192, 192, 192, 0 }; int oldshowflows = FALSE; int showflows = FALSE; int shortcut[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; int shortcutnum = 10; int matchtype = 0; 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 *shadow = NULL; /* for object moves */ SDL_Surface *bg = NULL; /* 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]; char oldstatustext[BUFLEN]; int rollover = FALSE; int oldmousepos = -1; int mousepos = 0; int oldselection = -1; int dontpaste = FALSE; SDL_Surface *toolbg; SDL_Surface *toolhilite; int curmap = 0; int startx,starty; int textanchor; char text[BUFLEN]; int startobj,endobj; int updateheight; char * textpos; // new char progdir[BUFLEN]; int shift; int autoload = FALSE; int main (int argc, char **argv) { int done; int c; int c2; int mod = FALSE; int tmod; int o; Uint32 oldticks = 0; Uint32 ticks; int doubleclick = FALSE; int n,found,delmap; int mx,my,mb; if (argc >= 2) { int i; strcpy(text, argv[1]); /* cope with spaces in filenames */ for (i = 2; i < argc; i++) { strcat(text, " "); strcat(text, argv[i]); } autoload = TRUE; } if (getenv("NETMAPRDIR") != NULL) { strncpy(progdir, getenv("NETMAPRDIR"), BUFLEN); } else { strcpy(progdir, "/usr/local/share/netmapr"); } if (strstr(argv[0], "view")) { readonly = TRUE; } /* if (readonly) { printf("Starting netmapr viewer v%s...\n", VERSION); } else { printf("Starting netmapr v%s...\n", VERSION); } */ if (initgraphics()) { printf("Error initialising graphics.\n"); exit(1); } atexit(cleanup); SDL_EnableUNICODE(1); if (autoload) { loadmap(); strcpy(text, ""); textpos = text; } if (readonly) { sprintf(statustext, "Welcome to netmapr viewer v%s. Author: rob@nethack.net", VERSION); } else { sprintf(statustext, "Welcome to netmapr v%s. Author: rob@nethack.net", VERSION); } strcpy(oldstatustext,statustext); drawscreen(); /* main loop */ done = 0; while (!done) { /* fade search result indicator */ if (searchflash > 0) { searchticks = SDL_GetTicks(); if (searchticks - oldsearchticks >= SEARCHFLASHSPEED) { searchflash--; /* show the found object */ switch (state) { case S_SAVING: case S_LOADING: case S_FGCOL: case S_MAPNAMING: case S_CREATETELE: case S_REALLYQUIT: case S_FILLCOL: case S_SEARCH: break; default: drawsearchflash(); break; } oldsearchticks = searchticks; } } /* fade error panel */ if (errorflash > 0) { errorticks = SDL_GetTicks(); if (errorticks - olderrorticks >= ERRORFLASHSPEED) { errorflash--; drawstatusbar(); olderrorticks = errorticks; } } /* fade info panel */ if (infoflash > 0) { infoticks = SDL_GetTicks(); if (infoticks - oldinfoticks >= INFOFLASHSPEED) { /* don't fade this if we're in a mode where the user has to do something special */ switch (state) { case S_MATCHX: case S_MATCHY: case S_MATCHSIZE: case S_CREATETELE: case S_CHANGEOBJECT: case S_DRAWFLOW: break; default: infoflash--; break; } drawstatusbar(); oldinfoticks = infoticks; } } /* check for input */ //while (SDL_PollEvent(&event)) { isevent = TRUE; if (infoflash || errorflash || searchflash) { if (!SDL_PollEvent(&event)) isevent = FALSE; } else { if (!SDL_WaitEvent(&event)) isevent = FALSE; } while (isevent) { switch (event.type) { case SDL_VIDEORESIZE: /* set screen size */ screen = SDL_SetVideoMode(event.resize.w > MINSCREENX ? event.resize.w : MINSCREENX, event.resize.h > MINSCREENY ? event.resize.h : MINSCREENY, //map[curmap].bpp, SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); map[curmap].bpp, SDL_SWSURFACE|SDL_RESIZABLE); SDL_FreeSurface(buffer); buffer = SDL_CreateRGBSurface(SDL_SWSURFACE,screen->w - SIDEBARW,screen->h - STATUSH, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); calcmapdimensions(); drawscreen(); break; case SDL_MOUSEBUTTONDOWN: searchflash = 0; if (isonxscrollbar(event.button.x, event.button.y)) { /* middle of the screen goes to where we clicked */ screenx = (((double)event.button.x / (double)(screen->w - SIDEBARW)) * map[curmap].width) - ((screen->w - SIDEBARW)/2); validatescreenpos(); drawxscrollbar(); changestate(S_XSCROLL); } else if (isonyscrollbar(event.button.x, event.button.y)) { /* middle of the screen goes to where we clicked */ screeny = (((double)event.button.y / (double)(screen->h - STATUSH - SBSIZE)) * map[curmap].height) - ((screen->h - STATUSH - SBSIZE)/2); validatescreenpos(); drawyscrollbar(); changestate(S_YSCROLL); } else if (isonmap(event.button.x, event.button.y)) { event.button.x += screenx; event.button.y += screeny; if (state == S_NONE) { mod = SDL_GetModState(); if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_SHIFT))) { /* centre map on clicked position */ screenx = event.button.x - ((screen->w - SIDEBARW)/2); screeny = event.button.y - ((screen->h - STATUSH)/2); validatescreenpos(); drawmap(TRUE); } else 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 { /* just clear the status text */ sprintf(statustext, "Ready."); drawstatusbar(); } } } 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 text o = textat(event.button.x, event.button.y); if (o != -1) { map[curmap].curtext = o; startresizetext(event.button.x,event.button.y); } else { // resize object o = objat(event.button.x, event.button.y); if (o != -1) { map[curmap].curobj = o; startresize(event.button.x,event.button.y); } } /* // 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) { int amt; tmod = SDL_GetModState(); if ((mod & KMOD_SHIFT)) { amt = (map[curmap].numthings / MULTIRAISENUM); } else amt = 1; if (map[curmap].selecteditem != -1) { /* raise the selected object */ raiseselected(amt); } } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { int amt; tmod = SDL_GetModState(); if ((mod & KMOD_SHIFT)) { amt = (map[curmap].numthings / MULTIRAISENUM); } else amt = 1; if (map[curmap].selecteditem != -1) { /* lower the selected object */ lowerselected(amt); } } } /* end if state = none */ } else if (isonobox(event.button.x, event.button.y)) { int amt = 1; tmod = SDL_GetModState(); if ((mod & KMOD_SHIFT)) { amt = 4; } if (event.button.button == SDL_BUTTON_WHEELUP) { scrollobox(-amt); } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { scrollobox(amt); } } break; case SDL_MOUSEBUTTONUP: searchflash = 0; 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 ((state == S_XSCROLL) || (state == S_YSCROLL)) { changestate(S_NONE); drawmap(TRUE); } else if (state == S_EDITTEXT) { endtextedit(); } else if (state == S_TYPETEXT) { endtext(); } else if (isonmap(event.button.x, event.button.y)) { event.button.x += screenx; event.button.y += screeny; 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 { seterror(255); sprintf(statustext, "Cannot drill down - object has no children (use drill tool to create one)."); map[curmap].selecteditem = -1; changestate(S_NONE); drawmap(TRUE); } } else { o = textat(event.button.x, event.button.y); if (o != -1) { startedittext(o); } } } } 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(TRUE); } } else if (state == S_DRAWFLOW) { int clickedtype = -1; o = textat(event.button.x, event.button.y); if (o == -1) { o = objat(event.button.x, event.button.y); if (o == -1) { o = getlinkat(event.button.x, event.button.y); if (o != -1) { clickedtype = T_LINK; } } else { clickedtype = T_OBJECT; } } else { clickedtype = T_TEXT; } if (clickedtype == -1) { /* reset to old showflows value */ changestate(S_NONE); drawmap(TRUE); } else { toggleflow(o, clickedtype); if (isflow(o, clickedtype)) { setinfo(255); sprintf(statustext, "%s #%d traffic flow status = TRUE.", typedesc[clickedtype], o); } else { setinfo(255); sprintf(statustext, "%s #%d traffic flow status = FALSE.", typedesc[clickedtype], o); } drawmap(TRUE); } } else if (state == S_REALLYQUIT) { o = getyn(event.button.x-screenx, event.button.y-screeny); if (o == YES) { done = TRUE; } else { changestate(S_NONE); drawmap(TRUE); } } else if (state == S_MATCHSIZE) { if (matchtype == T_OBJECT) { 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(TRUE); } } else if (matchtype == T_TEXT) { o = textat(event.button.x, event.button.y); if (o == -1) { changestate(S_NONE); sprintf(statustext, "Size match mode aborted."); drawstatusbar(); } else { int tw,th; /* resize selected text to match one which was clicked */ map[curmap].textob[map[curmap].selecteditem].h = map[curmap].textob[o].h; TTF_SizeText(font[map[curmap].textob[o].h], map[curmap].textob[map[curmap].selecteditem].text, &tw,&th); map[curmap].textob[map[curmap].selecteditem].w = tw; /* adjust offsets on all links to/from object */ changestate(S_NONE); sprintf(statustext, "Text #%d resized to match text #%d.",map[curmap].selecteditem,o); drawmap(TRUE); } } } else if (state == S_MATCHX) { if (matchtype == T_OBJECT) { 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(TRUE); } } else if (matchtype == T_TEXT) { o = textat(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 text */ map[curmap].textob[map[curmap].selecteditem].x = (map[curmap].textob[o].x + (map[curmap].textob[o].w/2)) - (map[curmap].textob[map[curmap].selecteditem].w/2); /* validate */ if (map[curmap].textob[map[curmap].selecteditem].x < 1) map[curmap].textob[map[curmap].selecteditem].x = 1; if (map[curmap].textob[map[curmap].selecteditem].x + map[curmap].textob[map[curmap].selecteditem].w > map[curmap].width) map[curmap].textob[map[curmap].selecteditem].x = map[curmap].width - map[curmap].textob[map[curmap].selecteditem].w; changestate(S_NONE); sprintf(statustext, "Text #%d X relocated to match text #%d.",map[curmap].selecteditem,o); drawmap(TRUE); } } } else if (state == S_MATCHY) { if (matchtype == T_OBJECT) { 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(TRUE); } } else if (matchtype == T_TEXT) { o = textat(event.button.x, event.button.y); if (o == -1) { changestate(S_NONE); sprintf(statustext, "Y position match mode aborted."); drawstatusbar(); } else { int curh, copyh; curh = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); copyh = TTF_FontHeight(font[map[curmap].textob[o].h]); /* move selected item to match one which was clicked */ map[curmap].textob[map[curmap].selecteditem].y = (map[curmap].textob[o].y + (copyh / 2)) - (curh / 2); /* validate */ if (map[curmap].textob[map[curmap].selecteditem].y < 1) map[curmap].textob[map[curmap].selecteditem].y = 1; if (map[curmap].textob[map[curmap].selecteditem].y + curh > map[curmap].height) map[curmap].textob[map[curmap].selecteditem].y = map[curmap].height - curh - 1; /* match middle of text */ changestate(S_NONE); sprintf(statustext, "Text #%d Y relocated to match text #%d.",map[curmap].selecteditem,o); drawmap(TRUE); } } } 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(TRUE); } 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(TRUE); } } else if (state == S_LINKMOVING) { /* has mouse actually moved? */ if ((event.button.x - screenx == startx) && (event.button.y - screeny == 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(TRUE); } 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(TRUE); } } 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(TRUE); } else { // actually move the link endlinkpointmove(event.button.x, event.button.y); changestate(S_NONE); drawmap(TRUE); } } 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(TRUE); } 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(TRUE); } } else if (state == S_LINKSRCMOVE) { // actually move the link src endpoint endlinksrcmove(event.button.x, event.button.y); changestate(S_NONE); drawmap(TRUE); } else if (state == S_LINKDSTMOVE) { // actually move the link dst endpoint endlinkdstmove(event.button.x, event.button.y); changestate(S_NONE); drawmap(TRUE); } else if (state == S_ADDOBJ) { /* create a new object */ createobject(map[curmap].selectedtype, event.button.x, event.button.y); drawmap(TRUE); 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; } updateheight = DEFTEXTH; strcpy(text, ""); textpos = text; bg = NULL; updatetextcursor(); changestate(S_TYPETEXT); } else if (state == S_FILLCOL) { getcolor(screen, event.button.x, event.button.y, &objfillcol); objfillcol.unused |= USECOLOUR; /* clear NOCOLOUR flag */ if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_OBJECT) { map[curmap].obj[map[curmap].selecteditem].fillcol = objfillcol; map[curmap].obj[map[curmap].selecteditem].fillcol.unused |= USECOLOUR; sprintf(statustext, "Fill colour of object #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, objfillcol.r,objfillcol.g,objfillcol.b); } else { sprintf(statustext, "Fill colour selected: R=%d,G=%d,B=%d",objfillcol.r,objfillcol.g,objfillcol.b); } } else { sprintf(statustext, "Fill colour selected: R=%d,G=%d,B=%d",objfillcol.r,objfillcol.g,objfillcol.b); } changestate(S_NONE); drawmap(TRUE); } else if (state == S_FGCOL) { getcolor(screen, event.button.x, event.button.y, &fgcol); if (map[curmap].selecteditem != -1) { int flow = isflow(map[curmap].selecteditem, map[curmap].selecteditemtype); if (map[curmap].selecteditemtype == T_LINK) { map[curmap].olink[map[curmap].selecteditem].col = fgcol; if (flow) { map[curmap].olink[map[curmap].selecteditem].col.unused |= ISFLOW; } 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; if (flow) { map[curmap].textob[map[curmap].selecteditem].c.unused |= ISFLOW; } 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(TRUE); } 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."); strcpy(oldstatustext, statustext); setmod(TRUE); changestate(S_NONE); drawmap(TRUE); } else if ((pos+maplistpos) <= (nummaps-1)) { if ((map[curmap].selecteditem != -1) && (map[curmap].selecteditemtype == T_OBJECT)) { if ((pos+maplistpos) != curmap) { map[curmap].obj[map[curmap].selecteditem].child = pos + maplistpos; sprintf(statustext, "Map link created."); strcpy(oldstatustext, statustext); setmod(TRUE); changestate(S_NONE); drawmap(TRUE); } else { seterror(255); 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(TRUE); } } else { sprintf(statustext, "Map link creation cancelled."); changestate(S_NONE); drawmap(TRUE); } } } else if (isonobox(event.button.x, event.button.y)) { int tempx,tempy; tempx = (event.button.x - obox.x) / (obox.gridsize+3); tempy = (event.button.y - obox.y) / (obox.gridsize+3); if (state == S_CHANGEOBJECT) { int seltype; seltype = tempy*obox.gridrowlen + tempx + (obox.pos*3); if (seltype >= numobjtypes) seltype = numobjtypes-1; if (map[curmap].selecteditemtype != T_OBJECT) { seterror(255); sprintf(statustext, "ERROR: Must select an object to change the type of!"); drawstatusbar(); } else if (map[curmap].selecteditem == -1) { seterror(255); sprintf(statustext, "ERROR: Must select an object to change the type of!"); drawstatusbar(); } else { sprintf(statustext, "Object #%d type changed from '%s' to '%s'.", map[curmap].selecteditem, objtype[map[curmap].obj[map[curmap].selecteditem].type].name, objtype[seltype].name); map[curmap].obj[map[curmap].selecteditem].type = seltype; state = S_NONE; drawtoolbox(); drawmap(TRUE); } } else { 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(); SDL_UpdateRect(screen, obox.x, obox.y, obox.width,obox.height); } 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 = ((screen->h - STATUSH)/2)-2; bg = NULL; strcpy(text, map[curmap].name); textpos = &text[strlen(text)]; changestate(S_MAPNAMING); drawmap(TRUE); break; } else if (isonmapboxchildren(event.button.x, event.button.y)) { if ((state != S_XSCROLL) && (state != S_YSCROLL)) { int pos; int th; /* calculate pixel size of mapbox text */ th = TTF_FontHeight(font[MAPBOXTEXTHEIGHT]); /* change to child */ pos = (event.button.y - (mapbox.y+(th*2)+1)) / th; /* adjust for offset if not a special value */ pos += mapbox.offset; if (pos >= numchildren) { seterror(255); 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; int boxy; tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); /* are we in a colour selection state? */ if (state == S_FGCOL) { /* set fgcol to black */ fgcol = black; sprintf(statustext, "Foreground colour selected: R=0,G=0,B=0"); changestate(S_NONE); drawmap(TRUE); break; } else if (state == S_FILLCOL) { /* set bgcol to 'nothing' */ objfillcol = black; objfillcol.unused &= ~(USECOLOUR); if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_OBJECT) { map[curmap].obj[map[curmap].selecteditem].fillcol = black; map[curmap].obj[map[curmap].selecteditem].fillcol.unused &= ~(USECOLOUR); sprintf(statustext, "Fill colour of object #%d removed.", map[curmap].selecteditem); } else { sprintf(statustext, "Fill colour removed."); } } else { sprintf(statustext, "Fill colour removed."); } changestate(S_NONE); drawmap(TRUE); break; } 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_COPY: copy(); break; case TB_FLOW: if (showflows) { setinfo(255); showflows = FALSE; sprintf(statustext, "Traffic flows hidden."); } else { setinfo(255); sprintf(statustext, "Traffic flows displayed."); showflows = TRUE; } drawtoolbox(); drawmap(TRUE); break; case TB_GRID: togglegrid(); drawmap(TRUE); break; case TB_NEW: if (readonly) { seterror(255); sprintf(statustext, "Cannot delete maps in read-only mode."); drawstatusbar(); break; } tmod = SDL_GetModState(); if (!(mod & KMOD_SHIFT)) { seterror(255); sprintf(statustext, "Must hold down SHIFT to start new project (avoids accidental loss of data)!"); drawstatusbar(); break; } initvars(); changestate(S_NONE); setinfo(255); sprintf(statustext, "All maps cleared."); sprintf(oldstatustext, statustext); drawmap(TRUE); break; case TB_LINESTYLE: if (map[curmap].selecteditemtype == T_LINK) { if (map[curmap].selecteditem != -1) { int si = map[curmap].selecteditem; /* TODO: add arrow */ /* where are we? */ if (event.button.y <= (boxy + 9)) { /* clear thickness */ map[curmap].olink[si].style &= 0xFFFF00; /* set to default */ map[curmap].olink[si].style |= defthickness; } else if (event.button.y <= (boxy + 19)) { /* clear style */ map[curmap].olink[si].style &= 0xFF00FF; /* set to default */ map[curmap].olink[si].style |= (defstyle << 8); } else { /* clear arrow */ map[curmap].olink[si].style &= 0x00FFFF; /* set to default */ map[curmap].olink[si].style |= (defarrow << 16); } setmod(TRUE); drawmap(TRUE); } else { seterror(255); sprintf(statustext, "No link selected!"); } } else { seterror(255); sprintf(statustext, "No link selected!"); } drawstatusbar(); break; case TB_MATCHSIZE: if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHSIZE); drawmap(TRUE); break; } } break; case TB_MATCHPOS: if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHX); drawmap(TRUE); break; } } break; case TB_PASTE: paste(); break; case TB_FGCOL: /* change selected item to match fgcol */ if (map[curmap].selecteditem != -1) { int flow = isflow(map[curmap].selecteditem, map[curmap].selecteditemtype); if (map[curmap].selecteditemtype == T_LINK) { map[curmap].olink[map[curmap].selecteditem].col = fgcol; /* maintain flow attribute */ if (flow) { map[curmap].olink[map[curmap].selecteditem].col.unused |= ISFLOW; } setmod(TRUE); 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; /* maintain flow attribute */ if (flow) { map[curmap].textob[map[curmap].selecteditem].c.unused |= ISFLOW; } setmod(TRUE); 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 { seterror(255); sprintf(statustext, "No object selected! (use RMB to select new foreground colour)"); } } else { seterror(255); sprintf(statustext, "No object selected! (use RMB to select new foreground colour)"); } drawmap(TRUE); break; case TB_FILLCOL: if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_OBJECT) { map[curmap].obj[map[curmap].selecteditem].fillcol = objfillcol; map[curmap].obj[map[curmap].selecteditem].fillcol.unused = objfillcol.unused; setmod(TRUE); if (objfillcol.unused & USECOLOUR) { sprintf(statustext, "Fill colour of object #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, objfillcol.r,objfillcol.g,objfillcol.b); } else { sprintf(statustext, "Fill colour of object #%d removed.",map[curmap].selecteditem); } } else { seterror(255); sprintf(statustext, "No object selected! (use RMB to select new fill colour)"); } } else { seterror(255); sprintf(statustext, "No object selected! (use RMB to select new fill colour)"); } drawmap(TRUE); break; case TB_DELETEMAP: /* safety - must hold down SHIFT to delete maps */ if (readonly) { seterror(255); sprintf(statustext, "Cannot delete maps in read-only mode."); drawstatusbar(); break; } tmod = SDL_GetModState(); if (!(mod & KMOD_SHIFT)) { seterror(255); sprintf(statustext, "Must hold down SHIFT to delete maps (avoids accidental loss of data)!"); drawstatusbar(); break; } if (curmap == 0) { seterror(255); sprintf(statustext, "Cannot delete toplevel map!"); drawstatusbar(); break; } delmap = curmap; /* any children in curent map? */ found = FALSE; for (n = 0; n < map[delmap].numobjects; n++) { if (map[delmap].obj[n].child != -1) { found = TRUE; break; } } if (found) { seterror(255); sprintf(statustext, "Cannot delete a map with children."); drawstatusbar(); break; } /* shuffle numbers on all other objects */ for (n = 0; n < nummaps; n++) { int o; for (o = 0; o < map[n].numobjects; o++) { if (map[n].obj[o].child == delmap) { map[n].obj[o].child = -1; } else if (map[n].obj[o].child > delmap) { map[n].obj[o].child--; } } } /* move all higher maps down by one */ for (n = delmap; n < (nummaps-1); n++) { map[n] = map[n+1]; } nummaps--; /* move far enough back to avoid all occurences of this map */ found = FALSE; for (n = 0; n < (numhistory-1); n++) { if (history[n+1] == delmap) { if (history[n] > delmap) { changemap(history[n] - 1); } else { changemap(history[n]); } numhistory = n+1; found = TRUE; break; } } if (!found) { goback(); setinfo(255); sprintf(statustext, "Deleted map #%d.\n",delmap); } /* fix history array */ for (n = 0; n < numhistory; n++) { if (history[n] > delmap) { history[n]--; } } drawmap(TRUE); break; case TB_CREATETELE: if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) { setinfo(255); sprintf(statustext,"Select destination map to link to..."); changestate(S_CREATETELE); drawmap(TRUE); } else { seterror(255); 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 { seterror(255); sprintf(statustext,"Cannot drill down - no object selected!"); drawstatusbar(); } break; case TB_SAVE: startx = 1; starty = ((screen->h - STATUSH)/2)-2; bg = NULL; strcpy(text, currentfilename); textpos = &text[strlen(text)]; changestate(S_SAVING); drawmap(TRUE); break; case TB_LOAD: startx = 1; starty = ((screen->h - STATUSH)/2)-2; bg = NULL; strcpy(text, currentfilename); textpos = &text[strlen(text)]; changestate(S_LOADING); drawmap(TRUE); 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 + screenx, event.button.y + screeny); if ((o != -1) && (o != startobj)) { endobj = o; endlink(event.button.x,event.button.y); changestate(S_NONE); drawmap(TRUE); } 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 = getlinkat(event.button.x + screenx, event.button.y + screeny); if (o != -1) { addlinkpoint(o, event.button.x+screenx, event.button.y+screeny); /* select the link */ map[curmap].selecteditemtype = T_LINK; map[curmap].selecteditem = o; drawmap(TRUE); } } } else if (event.button.button == SDL_BUTTON_RIGHT) { if (state == S_RESIZING) { // end resize endresize(event.button.x, event.button.y); changestate(S_NONE); drawmap(TRUE); } else if (state == S_TEXTRESIZING) { // end text resize endtextresize(event.button.x, event.button.y); changestate(S_NONE); } /* check for right click on toolbox */ if (isontoolbox(event.button.x, event.button.y)) { int tempx,tempy, selection,boxy; tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); selection = tempy*toolbox.gridrowlen + tempx; switch (selection) { case TB_ADDOBJ: if (map[curmap].selecteditemtype != T_OBJECT) { seterror(255); sprintf(statustext, "Must select an object to change the type of first!"); drawstatusbar(); } else if (map[curmap].selecteditem == -1) { seterror(255); sprintf(statustext, "Must select an object to change the type of first!"); drawstatusbar(); } else { changestate(S_CHANGEOBJECT); } break; case TB_ADDTEXT: if (state == S_NONE) { if ( (map[curmap].selecteditemtype == T_TEXT) && (map[curmap].selecteditem != -1) ){ startedittext(map[curmap].selecteditem); } else { seterror(255); sprintf(statustext, "Cannot edit text - no text item selected!"); drawstatusbar(); } } break; case TB_GRID: changegridsize(); drawmap(TRUE); break; case TB_FLOW: oldshowflows = showflows; showflows = TRUE; drawtoolbox(); changestate(S_DRAWFLOW); drawmap(TRUE); break; case TB_FGCOL: changestate(S_FGCOL); drawmap(TRUE); break; case TB_FILLCOL: changestate(S_FILLCOL); drawmap(TRUE); break; case TB_MATCHPOS: /* match y */ if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHY); drawmap(TRUE); break; } } break; case TB_LINESTYLE: /* figure out where in the box we are */ if (event.button.y <= (boxy + 9)) { changelinethickness(1); } else if (event.button.y <= (boxy + 19)) { changelinestyle(1); } else { changelinearrow(1); } drawstatusbar(); break; } } } 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; case S_NONE: /* has mouse moved since last time? */ mousepos = getmousepos(event.button.x, event.button.y); if ((mousepos != oldmousepos ) || (mousepos== MP_TOOLBOX)) { /* rollovers */ if (mousepos == MP_TOOLBOX) { SDL_Rect area; int tempx,tempy, selection; int boxy; if (!rollover) strcpy(oldstatustext, statustext); rollover = TRUE; /* determine which button we're over */ tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); selection = tempy*toolbox.gridrowlen + tempx; /* replace old button */ if (toolbg != NULL) { SDL_Rect area; if (oldselection >= 0) { if (dontpaste == FALSE) { area.x = toolbox.x + ((oldselection % 3 )*(toolbox.gridsize+3)); area.y = toolbox.y + ((oldselection / 3)*(toolbox.gridsize+3)); area.w = toolbox.gridsize; area.h = toolbox.gridsize; SDL_BlitSurface(toolbg, NULL, screen, &area); SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } else { dontpaste = FALSE; } } SDL_FreeSurface(toolbg); toolbg = NULL; } /* copy background of this button */ if (selection <= TB_SAVE) { toolbg = SDL_CreateRGBSurface(SDL_SWSURFACE,toolbox.gridsize+3, toolbox.gridsize+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); area.x = toolbox.x + ((selection % 3 )*(toolbox.gridsize+3)); area.y = toolbox.y + ((selection / 3)*(toolbox.gridsize+3)); area.w = toolbox.gridsize+1; area.h = toolbox.gridsize+1; SDL_BlitSurface(screen,&area, toolbg, 0); /* draw highlight */ if (selection == TB_LINESTYLE) { SDL_Rect sarea; if (event.button.y <= (boxy + 9)) { sarea.x = 0; sarea.y = 0; sarea.w = toolbox.gridsize; sarea.h = 11; area.h = 11; area.y += 1; } else if (event.button.y <= (boxy + 19)) { sarea.x = 0; sarea.y = 0; sarea.w = toolbox.gridsize; sarea.h = 10; area.h = 10; area.y += 12; } else { sarea.x = 0; sarea.y = 0; sarea.w = toolbox.gridsize; sarea.h = 8; area.h = 8; area.y += 21; } SDL_BlitSurface(toolhilite, &sarea, screen, &area); } else { SDL_BlitSurface(toolhilite, NULL, screen, &area); } SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } if (selection != oldselection) { switch (selection) { case TB_POINTER: sprintf(statustext, "LMB = Enter object selection mode"); drawstatusbar(); break; case TB_ADDOBJ: sprintf(statustext, "LMB = Add an object to the map, RMB = Change object type"); drawstatusbar(); break; case TB_ADDTEXT: sprintf(statustext, "LMB (on map) = Add text to the map, LMB (on object) = Add text to an object"); drawstatusbar(); break; case TB_COPY: sprintf(statustext, "LMB = Copy the current object/text/map"); drawstatusbar(); break; case TB_PASTE: sprintf(statustext, "LMB = Paste the current copy buffer"); drawstatusbar(); break; case TB_GRID: sprintf(statustext, "LMB = Toggle grid on/off, RMB = Change grid size"); drawstatusbar(); break; case TB_FGCOL: sprintf(statustext, "LMB = Apply default foreground colour to current selection, RMB = Change default foreground colour"); drawstatusbar(); break; case TB_FILLCOL: sprintf(statustext, "LMB = Apply default fill colour to current selection, RMB = Change default fill colour"); drawstatusbar(); break; case TB_LINESTYLE: if (event.button.y <= (boxy + 9)) { sprintf(statustext, "LMB = Apply default thickness to current line, RMB = Change default line thickness"); } else if (event.button.y <= (boxy + 19)) { sprintf(statustext, "LMB = Apply default style to current line, RMB = Change default line style"); } else { sprintf(statustext, "LMB = Apply default arrowhead type to current line, RMB = Change default arrowhead type"); } drawstatusbar(); break; case TB_MATCHSIZE: sprintf(statustext, "LMB = Match size of current selection to next item clicked"); drawstatusbar(); break; case TB_MATCHPOS: sprintf(statustext, "LMB = Match horizontal position of currently selected item to next item clicked, RMB = match vertical position"); drawstatusbar(); break; case TB_FLOW: sprintf(statustext, "LMB = Toggle display of traffic flows, RMB = Enter traffic flow definition mode"); drawstatusbar(); break; case TB_DRILLDOWN: sprintf(statustext, "LMB = Drill down to create new map under current object"); drawstatusbar(); break; case TB_CREATETELE: sprintf(statustext, "LMB = Set destination map for when current object is double-clicked"); drawstatusbar(); break; case TB_DELETEMAP: sprintf(statustext, "LMB = Delete current map (hold down SHIFT to confirm)"); drawstatusbar(); break; case TB_NEW: sprintf(statustext, "LMB = Delete ALL maps and start a fresh project (hold SHIFT to confirm)"); drawstatusbar(); break; case TB_LOAD: sprintf(statustext, "LMB = Load a new map"); drawstatusbar(); break; case TB_SAVE: sprintf(statustext, "LMB = Save the current map to disk (will automatically export based on extensions of BMP/PNG/SVG)"); drawstatusbar(); break; default: break; } } oldselection = selection; } else if (mousepos == MP_MAPBOXNAME) { if (!rollover) strcpy(oldstatustext, statustext); rollover = TRUE; sprintf(statustext, "LMB = Rename the current map."); drawstatusbar(); } else if (mousepos == MP_MAPBOXCHILDREN) { if (!rollover) strcpy(oldstatustext, statustext); rollover = TRUE; sprintf(statustext, "LMB = Drill down into a submap (blue text indicates maps already in the map history)."); drawstatusbar(); } else if (mousepos == MP_OBJECTBOX) { if (!rollover) strcpy(oldstatustext, statustext); rollover = TRUE; sprintf(statustext, "LMB = Select a new object type."); drawstatusbar(); } else { strcpy(statustext, oldstatustext); strcpy(oldstatustext, ""); drawstatusbar(); rollover = FALSE; } } oldmousepos = mousepos; break; } /* scrollbar drags */ mb = SDL_GetMouseState(&mx,&my); //if (isonxscrollbar(mx,my)) { if (state == S_XSCROLL) { if (mb & SDL_BUTTON(1)) { /* if lmb is depressed */ screenx = (((double)event.button.x / (double)(screen->w - SIDEBARW)) * map[curmap].width) - ((screen->w - SIDEBARW)/2); validatescreenpos(); drawxscrollbar(); } } //if (isonyscrollbar(mx,my)) { if (state == S_YSCROLL) { if (mb & SDL_BUTTON(1)) { /* if lmb is depressed */ screeny = (((double)event.button.y / (double)(screen->h - STATUSH - SBSIZE)) * map[curmap].height) - ((screen->h - STATUSH - SBSIZE)/2); validatescreenpos(); drawyscrollbar(); } } break; case SDL_QUIT: if (modified) { strcpy(text, "Changes not saved - really quit?"); changestate(S_REALLYQUIT); drawmap(TRUE); } else { done = TRUE; } break; case SDL_VIDEOEXPOSE: /* redraw screen */ drawscreen(); break; case SDL_KEYDOWN: c = event.key.keysym.unicode & 0x7F; c2 = 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) || (state == S_EDITTEXT) || (state == S_SEARCH)) { if ((c2 == 'u') && (mod & KMOD_CTRL)) { // delete from start to text pos strcpy(text, textpos); //text[0] = '\0'; textpos = text; updatetextcursor(); } else if ((c2 == 'k') && (mod & KMOD_CTRL)) { // delete from here to end *textpos = '\0'; updatetextcursor(); } else if ((c2 == 'a') && (mod & KMOD_CTRL)) { // go to start of text textpos = text; updatetextcursor(); } else if ((c2 == 'e') && (mod & KMOD_CTRL)) { // go to end of text textpos = &text[strlen(text)]; updatetextcursor(); } else if ((c >= FIRSTLET) && (c <= LASTLET)) { // add onto end of text char temptext[2]; char endbit[BUFLEN]; // remember from here until end if (textpos) { strcpy(endbit, textpos); } else { endbit[0] = '\0'; } // end here *textpos = '\0'; // append char sprintf(temptext, "%c", c); strcat(text, temptext); // move cursor to end of appended bit textpos = &text[strlen(text)]; // append end bit if (strlen(endbit) > 0) { strcat(text, endbit); } // updatetextcursor(); } else if (c2 == SDLK_LEFT) { // move cursor if (textpos != text) textpos--; updatetextcursor(); } else if (c2 == SDLK_RIGHT) { if (textpos != &text[strlen(text)]) textpos++; updatetextcursor(); } else if ((c2 == SDLK_ESCAPE) || ((c2 == 'g') && (mod & KMOD_CTRL)) ) { sprintf(statustext, "Aborted."); changestate(S_NONE); drawmap(TRUE); } else if (c == ' ') { // add onto end of text char endbit[BUFLEN]; // remember from here until end strcpy(endbit, textpos); // end here *textpos = '\0'; // append char strcat(text, " "); // move cursor to end of appended bit textpos = &text[strlen(text)]; // append end bit strcat(text, endbit); updatetextcursor(); } else if (c2 == SDLK_BACKSPACE) { // remove last charater if (textpos != text) { strcpy(textpos-1, textpos); } //text[strlen(text)-1] = '\0'; textpos--; updatetextcursor(); } else if (c == 13) { /* enter */ if (state == S_TYPETEXT) { endtext(); } else if (state == S_EDITTEXT) { endtextedit(); } else if (state == S_SAVING) { savemap(); changestate(S_NONE); drawmap(TRUE); } else if (state == S_LOADING) { loadmap(); changestate(S_NONE); drawmap(TRUE); } else if (state == S_SEARCH) { changestate(S_NONE); if (dosearch()) { seterror(255); sprintf(statustext, "Not found: '%s'",searchtext); setsearchflash(0); } else { setinfo(255); sprintf(statustext, "Found '%s' in text object #%d (map '%s')",searchtext, map[curmap].selecteditem, map[curmap].name); setsearchflash(255); } drawmap(TRUE); } else if (state == S_MAPNAMING) { /* rename map */ strcpy(map[curmap].name,text); changestate(S_NONE); setinfo(255); sprintf(statustext, "Map #%d renamed to '%s'.",curmap,map[curmap].name); drawmap(TRUE); } } } else { if (c2 == SDLK_HOME) { screenx = 0; screeny = 0; drawmap(TRUE); } if (c2 == SDLK_END) { screenx = map[curmap].width - (screen->w-SIDEBARW); screeny = map[curmap].height - (screen->h-STATUSH); drawmap(TRUE); } if (c == 'a') { /* add map[curmap].object */ if (state == S_NONE) { changestate(S_ADDOBJ); } } if (c == '/') { /* search/find */ if (state == S_NONE) { startx = 1; starty = ((screen->h-STATUSH)/2)-2; bg = NULL; strcpy(text, ""); textpos = text; changestate(S_SEARCH); drawmap(TRUE); } } if (c == 'n') { /* find next */ changestate(S_NONE); if (dosearchnext()) { seterror(255); sprintf(statustext, "Not foundnext: '%s'",searchtext); setsearchflash(0); } else { setinfo(255); sprintf(statustext, "Foundnext %s'%s' in text object #%d (map '%s')",searchwrap ? "(wrapped) " : "",searchtext, map[curmap].selecteditem, map[curmap].name); setsearchflash(255); } drawmap(TRUE); } if (c == 'm') { /* modify object type */ if (state == S_NONE) { changestate(S_CHANGEOBJECT); } } if (c == 't') { /* add text */ if (state == S_NONE) { changestate(S_ADDTEXT); } } if ((c == 'e') || (c2 == SDLK_F2)) { /* edit current text */ if (state == S_NONE) { if ( (map[curmap].selecteditemtype == T_TEXT) && (map[curmap].selecteditem != -1) ){ startedittext(map[curmap].selecteditem); } else { seterror(255); sprintf(statustext, "Cannot edit text - no text item selected!"); drawstatusbar(); } } } if (c == 's') { /* save */ startx = 1; starty = ((screen->h-STATUSH)/2)-2; bg = NULL; strcpy(text, currentfilename); textpos = &text[strlen(text)]; changestate(S_SAVING); drawmap(TRUE); } if ((c == 'l') || (c == 'o')) { /* load, open */ startx = 1; starty = ((screen->h-STATUSH)/2)-2; bg = NULL; strcpy(text, currentfilename); textpos = &text[strlen(text)]; changestate(S_LOADING); drawmap(TRUE); } if ((c == ',') || (c == 'q')) { /* scroll object box up */ if (state == S_CREATETELE) { scrollmaplist(-1); } else { scrollobox(-1); } } if ((c == '.') || (c == 'w')) { /* scroll object box down */ if (state == S_CREATETELE) { scrollmaplist(1); } else { scrollobox(1); } } if ((c == '<') || (c == 'Q')) { /* scroll object box up */ if (state == S_CREATETELE) { scrollmaplist(-20); } else { scrollobox(-OBOXPAGESIZE); } } if ((c == '>') || (c == 'W')) { /* scroll object box down */ if (state == S_CREATETELE) { scrollmaplist(20); } else { scrollobox(OBOXPAGESIZE); } } if (c == 'x') { if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHX); drawmap(TRUE); break; } } } if (c == 'y') { if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHY); drawmap(TRUE); break; } } } if (c == 'b') { if (map[curmap].selecteditem != -1) { switch (map[curmap].selecteditemtype) { case T_OBJECT: case T_TEXT: matchtype = map[curmap].selecteditemtype; changestate(S_MATCHSIZE); drawmap(TRUE); break; } } } if (c == 'g') { /* toggle snap-to-grid */ togglegrid(); drawtoolbox(); } if (c == ';') { /* change gridsize */ changegridsize(); drawmap(TRUE); } if (c == 'c') { /* copy */ copy(); } 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 { seterror(255); sprintf(statustext,"Cannot drill down - no object selected!"); drawstatusbar(); } } else { seterror(255); sprintf(statustext,"Cannot drill down in state %d.",state); drawstatusbar(); } } if (c == 'f') { if (showflows) { showflows = FALSE; setinfo(255); sprintf(statustext, "Traffic flows hidden."); } else { setinfo(255); sprintf(statustext, "Traffic flows displayed."); showflows = TRUE; } drawtoolbox(); drawmap(TRUE); } if ((c == 'p') || (c == 'v')) { /* paste */ paste(); } /* keyboard shortcuts */ if ((c >= '0') && (c <= '9')) { int mx,my; int onum; onum = c - '0'; SDL_GetMouseState(&mx, &my); if (isonobox(mx, my)) { int seltype, tempx, tempy; /* define shortcut */ tempx = (mx - obox.x) / (obox.gridsize+3); tempy = (my - obox.y) / (obox.gridsize+3); seltype = tempy*obox.gridrowlen + tempx + (obox.pos*3); shortcut[onum] = seltype; setinfo(255); sprintf(statustext,"Shortcut key '%c' set to '%s'.\n",c, objtype[seltype].name); drawstatusbar(); drawobox(); } else { /* select shortcut */ int fitx, fity, fit; /* select object */ map[curmap].selectedtype = shortcut[onum]; /* these two should never happen... */ if (map[curmap].selectedtype < 0 ) map[curmap].selectedtype = 0; if (map[curmap].selectedtype >= numobjtypes) map[curmap].selectedtype = numobjtypes-1; /* ensure that object is visible */ fitx = (obox.width / obox.gridsize); fity = ((obox.height+3) / obox.gridsize); fit = fitx * fity; /* scroll object box to make it visible */ while (shortcut[onum] < (obox.pos*fitx)) { obox.pos--; } while (shortcut[onum] > ((obox.pos*fitx) + fit)) { obox.pos++; } sprintf(statustext,"Object type shortcut #%d ('%s') selected.\n",onum, objtype[map[curmap].selectedtype].name); drawstatusbar(); drawobox(); SDL_UpdateRect(screen, obox.x, obox.y, obox.width,obox.height); } } if (c2 == SDLK_BACKSPACE) { goback(); } if (c2 == SDLK_PAGEUP) { scrollobox(-OBOXPAGESIZE); } if (c2 == SDLK_PAGEDOWN) { scrollobox(OBOXPAGESIZE); } if (c2 == 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(TRUE); } else { deletething(map[curmap].selecteditem,map[curmap].selecteditemtype); } } } if (map[curmap].selecteditem != -1) { if (c == ']') { /* raise */ int amt; tmod = SDL_GetModState(); if ((tmod & KMOD_SHIFT)) { amt = (map[curmap].numthings / MULTIRAISENUM); } else amt = 1; /* raise the selected map[curmap].object */ raiseselected(amt); } if (c == '[') { /* lower */ int amt; tmod = SDL_GetModState(); if ((tmod & KMOD_SHIFT)) { amt = (map[curmap].numthings / MULTIRAISENUM); } else amt = 1; /* lower the selected map[curmap].object */ lowerselected(amt); } if (c == '{') { /* lower by lots */ int amt = (map[curmap].numthings / MULTIRAISENUM); lowerselected(amt); } if (c == '}') { /* raise by lots */ int amt = (map[curmap].numthings / MULTIRAISENUM); raiseselected(amt); } } } break; } if (infoflash || errorflash) { if (!SDL_PollEvent(&event)) isevent = FALSE; } else { isevent = FALSE; } } } /* 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; setmod(TRUE); sprintf(statustext, "Point added to link #%d at position %d,%d.",linkid, x, y); } int addvector(vectorimg_t *vimg, int type, int x1, int y1, int x2, int y2, SDL_Color *c, SDL_Color *fc) { 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->vector[vimg->vnum].c.unused = 0; if (fc == NULL) { vimg->vector[vimg->vnum].fc.r = 0; vimg->vector[vimg->vnum].fc.g = 0; vimg->vector[vimg->vnum].fc.b = 0; vimg->vector[vimg->vnum].fc.unused = 0; } else { vimg->vector[vimg->vnum].fc.r = fc->r; vimg->vector[vimg->vnum].fc.g = fc->g; vimg->vector[vimg->vnum].fc.b = fc->b; vimg->vector[vimg->vnum].fc.unused = fc->unused; } vimg->vnum = vimg->vnum + 1; return FALSE; } void calcmapdimensions(void) { int thismaxx,thismaxy; /* used to calculate map size */ int maxx = -1,maxy = -1; /* used to calculate map size */ int i; /* draw all map[curmap].objects links etc*/ for (i = 0; i < map[curmap].numthings; i++) { if (map[curmap].thing[i].type == T_OBJECT) { /* calculate max map size */ thismaxx = map[curmap].obj[map[curmap].thing[i].id].x + map[curmap].obj[map[curmap].thing[i].id].w; thismaxy = map[curmap].obj[map[curmap].thing[i].id].y + map[curmap].obj[map[curmap].thing[i].id].h; if (thismaxx > maxx) maxx = thismaxx; if (thismaxy > maxy) maxy = thismaxy; } else if (map[curmap].thing[i].type == T_LINK) { int p; thismaxx = -1; thismaxy = -1; for (p = 0; p < map[curmap].olink[map[curmap].thing[i].id].npoints; p++) { if (map[curmap].olink[map[curmap].thing[i].id].point[p].x > thismaxx) thismaxx = map[curmap].olink[map[curmap].thing[i].id].point[p].x; if (map[curmap].olink[map[curmap].thing[i].id].point[p].y > thismaxy) thismaxy = map[curmap].olink[map[curmap].thing[i].id].point[p].y; } /* calculate max map size */ if (thismaxx > maxx) maxx = thismaxx; if (thismaxy > maxy) maxy = thismaxy; } else if (map[curmap].thing[i].type == T_TEXT) { /* calculate max map size */ thismaxx = map[curmap].textob[map[curmap].thing[i].id].x + map[curmap].textob[map[curmap].thing[i].id].w; thismaxy = map[curmap].textob[map[curmap].thing[i].id].y + map[curmap].textob[map[curmap].thing[i].id].h; if (thismaxx > maxx) maxx = thismaxx; if (thismaxy > maxy) maxy = thismaxy; } else { printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type); } } /* set map dimensions - automatically grow/shrink to be a bit bigger than required size */ if (maxx <= (map[curmap].width - 300)) map[curmap].width = maxx + 100; if (maxy <= (map[curmap].height - 300)) map[curmap].height = maxx + 100; if (maxx+200 > map[curmap].width) map[curmap].width = maxx + 200; if (maxy+200 > map[curmap].height) map[curmap].height = maxy + 200; /* make sure map is always at least as big as the visible screen size */ if (map[curmap].width < screen->w - SIDEBARW) map[curmap].width = screen->w - SIDEBARW; if (map[curmap].height < screen->h - STATUSH) map[curmap].height = screen->h - STATUSH; /* determine position of sidebar */ obox.x = screen->w - SIDEBARW; obox.y = ((screen->h / 4) * 3) - 10; obox.width = SIDEBARW; obox.height = screen->h - obox.y; obox.bgcol = black; obox.gridbgcol = grey; obox.gridcol = grey; obox.gridsize = 30; obox.gridrowlen = SIDEBARW / obox.gridsize; toolbox.x = screen->w - SIDEBARW; toolbox.y = 0; toolbox.width = SIDEBARW; toolbox.height = screen->h / 3; toolbox.bgcol = black; toolbox.gridsize = 30; toolbox.gridrowlen = SIDEBARW / toolbox.gridsize; mapbox.x = screen->w - SIDEBARW; mapbox.y = toolbox.y+toolbox.height+10; mapbox.width = SIDEBARW; mapbox.height = obox.y - mapbox.y - 20; mapbox.offset = 0; } int setgridsize(int size) { int n; for (n = 0; n < gridsizenum; n++) { if (gridsizelist[n] == size) { gridsizeindex = n; gridsize = gridsizelist[n]; return FALSE; } } return TRUE; } void changegridsize(void) { if (++gridsizeindex >= gridsizenum) { gridsizeindex = 0; } gridsize = gridsizelist[gridsizeindex]; setinfo(255); sprintf(statustext, "Grid size set to %d.", gridsize); } void changelinearrow(int changeby) { if ((changeby < 0) && (defarrow == 0)) { defarrow = AP_BOTH; } else { defarrow += changeby; } /* wrap around */ if (defarrow > AP_BOTH) defarrow = 0; /* change arrow style on currently selected line */ if (map[curmap].selecteditemtype == T_LINK) { if (map[curmap].selecteditem != -1) { map[curmap].olink[map[curmap].selecteditem].style &= 0x00ffff; map[curmap].olink[map[curmap].selecteditem].style |= (defarrow << 16); setmod(TRUE); drawmap(TRUE); } } /* redraw toolbox */ drawtoolbox(); } void changelinestyle(int changeby) { if ((changeby < 0) && (defstyle == 0)) { defstyle = MAXLINESTYLE - 1; } else { defstyle += changeby; } /* wrap around */ if (defstyle >= MAXLINESTYLE) defstyle = 0; /* change line style of currently selected line */ if (map[curmap].selecteditemtype == T_LINK) { if (map[curmap].selecteditem != -1) { map[curmap].olink[map[curmap].selecteditem].style &= 0xff00ff; map[curmap].olink[map[curmap].selecteditem].style |= (defstyle << 8); setmod(TRUE); drawmap(TRUE); } } /* redraw toolbox */ drawtoolbox(); } void changelinethickness(int changeby) { defthickness += changeby; /* wrap around */ if (defthickness <= 0) defthickness = 5; if (defthickness > 5) defthickness = 1; /* change thickness of currently selected line */ if (map[curmap].selecteditemtype == T_LINK) { if (map[curmap].selecteditem != -1) { map[curmap].olink[map[curmap].selecteditem].style &= 0xffff00; map[curmap].olink[map[curmap].selecteditem].style |= defthickness; setmod(TRUE); drawmap(TRUE); } } /* redraw toolbox */ drawtoolbox(); } void changemap(int newmap) { map[newmap].selecteditem = -1; map[newmap].selecteditemtype = -1; /*map[newmap].selectedtype = map[curmap].selectedtype; */ curmap = newmap; } void changestate(int newstate) { int oldstate; oldstate = state; /* can't do most things in readonly mode */ if (readonly) { switch (newstate) { case S_NONE: case S_LOADING: case S_REALLYQUIT: break; default: newstate = S_NONE; break; } } if (newstate != state) { if (oldstate == S_DRAWFLOW) { showflows = oldshowflows; } 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; if (oldstate == S_DRAWFLOW) { drawmap(TRUE); } drawtoolbox(); switch (state) { case S_NONE: //sprintf(statustext,"Selection mode enabled.\n"); fflush(STDOUT); if (oldstate == S_DRAWFLOW) { sprintf(statustext,"Traffic flow definition complete."); } break; case S_ADDOBJ: sprintf(statustext,"Object creation mode enabled.\n"); break; case S_CHANGEOBJECT: setinfo(255); sprintf(statustext,"Object type modification mode enabled - select new object type...\n"); break; case S_ADDTEXT: sprintf(statustext,"Text creation mode entered.\n"); break; case S_TYPETEXT: sprintf(statustext,"Text entry mode entered.\n"); break; case S_EDITTEXT: sprintf(statustext,"Text edit mode entered.\n"); break; case S_MATCHSIZE: setinfo(255); sprintf(statustext,"Size-matching mode entered - select object to copy size from...\n"); break; case S_MATCHX: setinfo(255); sprintf(statustext,"X-matching mode entered - select item to align with...\n"); break; case S_MATCHY: setinfo(255); sprintf(statustext,"Y-matching mode entered - select item to align with...\n"); break; case S_DRAWFLOW: setinfo(255); sprintf(statustext,"Traffic flow definition mode entered - select items...\n"); break; case S_MAPNAMING: sprintf(statustext,"Map rename mode entered.\n"); break; case S_SEARCH: sprintf(statustext,"Search mode entered.\n"); break; case S_SAVING: sprintf(statustext,"Save mode entered.\n"); break; case S_LOADING: sprintf(statustext,"Load mode entered.\n"); break; case S_XSCROLL: sprintf(statustext,"Scrolling horizontally...\n"); break; case S_YSCROLL: sprintf(statustext,"Scrolling vertically...\n"); break; } drawstatusbar(); } } void cleanup(void) { int i; SDL_FreeCursor(textmouse); SDL_FreeCursor(objmouse); for (i = 1; i < MAXLETTERHEIGHT; i++) { TTF_CloseFont(font[i]); } TTF_Quit(); SDL_EnableUNICODE(0); SDL_Quit(); } void copy(void) { if (map[curmap].selecteditem == -1) { /* copy entire map */ copytype = T_MAP; copyfrom = -1; copymap = curmap; sprintf(statustext,"Map %d ('%s') set as copy source.",curmap, map[curmap].name); drawstatusbar(); } else { if (map[curmap].selecteditemtype == T_OBJECT) { copytype = T_OBJECT; copymap = curmap; copyfrom = map[curmap].selecteditem; sprintf(statustext,"Object %d set as copy source.",copyfrom); drawstatusbar(); } else if (map[curmap].selecteditemtype == T_TEXT) { copytype = T_TEXT; copymap = curmap; copyfrom = map[curmap].selecteditem; sprintf(statustext,"Text %d ('%s') set as copy source.",copyfrom, map[curmap].textob[copyfrom].text); drawstatusbar(); } } } 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; } /* adjust for grid */ if (grid) { x = x - (x % gridsize); y = y - (y % gridsize); } map[curmap].obj[map[curmap].numobjects].x = x; map[curmap].obj[map[curmap].numobjects].y = y; map[curmap].obj[map[curmap].numobjects].child = -1; map[curmap].obj[map[curmap].numobjects].fillcol.unused &= ~ISFLOW; /* not a flow */ setmod(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--; } } } setmod(TRUE); map[curmap].selecteditem = -1; map[curmap].selecteditemtype = -1; drawmap(TRUE); } 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 { seterror(255); sprintf(statustext,"Can't find matching thing for link #%d!\n",linkid); } setmod(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 { seterror(255); sprintf(statustext,"Can't find matching thing for object #%d!\n",oid); } setmod(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 { seterror(255); sprintf(statustext,"Can't find matching thing for text item #%d!\n",textid); } setmod(TRUE); sprintf(statustext,"Deleted text item #%d.\n",textid); drawstatusbar(); } void adjustendpoint(SDL_Surface *screen, int *adjx, int *adjy, double x1, double y1, double x2, double y2, int arrowstyle, int arrowpos ) { int middlex, middley; int deltax, deltay; int numpixels; int d; int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; int i,n; int x; int y; int tempx,tempy; int o,oldo; SDL_Surface *temps; int arrowthickness; arrowthickness = (arrowstyle & 0x0000ff); /* calculate where the arrowpoint should go - follow the line until we're not on an object */ if (arrowpos == AP_END) { /* temporarily reverse endpoints */ tempx = x1; tempy = y1; x1 = x2; y1 = y2; x2 = tempx; y2 = tempy; } 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; middlex = -1; middley = -1; /* temps = SDL_CreateRGBSurface(SDL_SWSURFACE,10,10, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); */ temps = NULL; o = -1; oldo = -99; for (i = 0; i < numpixels; i++) { o = objat(x,y); if (o == -1) { middlex = x; middley = y; break; } else { int ox,oy; SDL_Color tempc; if (o != oldo) { if (oldo == -99) { SDL_Rect area; int tid; temps = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].obj[o].w+3, map[curmap].obj[o].h+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); area.x = map[curmap].obj[o].x; area.y = map[curmap].obj[o].y; area.w = map[curmap].obj[o].w; area.h = map[curmap].obj[o].h; /* have we already drawn the object? */ /* get thingid of this object */ tid = -1; for (n = 0; n < map[curmap].numthings; n++) { if ( (map[curmap].thing[n].id == o) && (map[curmap].thing[n].type == T_OBJECT) ) { tid = n; break; } } /* FIXME: drawobject is too slow here!!! */ /* but we can't just blit from the screen, in case the object hasn't been drawn yet */ drawobject(temps, &map[curmap].obj[o], FALSE, TRUE); /* if (tid == -1) { drawobject(temps, &map[curmap].obj[o], FALSE); } else if (thingdrawn[tid] == FALSE) { drawobject(temps, &map[curmap].obj[o], FALSE); } else { SDL_BlitSurface(screen, &area, temps, NULL); } */ oldo = o; } else { if (temps != NULL) { SDL_FreeSurface(temps); temps = NULL; } middlex = x; middley = y; break; } } /* we can start drawing if we're on the object but on a transparent bit */ ox = x - map[curmap].obj[o].x; oy = y - map[curmap].obj[o].y; getcolor(temps, ox + arrowthickness - 1, oy + arrowthickness -1, &tempc); if ( (tempc.r == map[curmap].bgcol.r) && (tempc.g == map[curmap].bgcol.g) && (tempc.b == map[curmap].bgcol.b)) { /* free temporary surface */ SDL_FreeSurface(temps); temps = NULL; middlex = x; middley = y; break; } } if (d < 0) { d += dinc1; x += xinc1; y += yinc1; } else { d += dinc2; x += xinc2; y += yinc2; } } if (temps != NULL) { SDL_FreeSurface(temps); temps = NULL; } *adjx = middlex; *adjy = middley; } int dosearch(void) { int i; int m; /* fill in search text */ strcpy(searchtext, text); /* reset search point */ searchmap = 0; searchtob = 0; searchwrap = FALSE; /* go through each text object until we find what we're looking for */ for (m = 0; m < nummaps; m++) { /* for each map */ for (i = 0; i < map[m].numtext; i++) { /* for each text object */ /* does it contain the search string? */ if (strstr(map[m].textob[i].text, searchtext)) { drillto(m); map[m].selecteditemtype = T_TEXT; map[m].selecteditem = i; searchmap = m; searchtob = i; return FALSE; } } } return TRUE; } int dosearchnext(void) { int i = -1; int firsttime = TRUE; int m; int numtextfound = 0; /* go through each text object until we find what we're looking for */ for (m = searchmap; ; m++) { /* for each map */ if (m >= nummaps) { m = 0; searchwrap = TRUE; } if ((m == searchmap) && (numtextfound == 0) && (!firsttime)) { /* no text objects exist */ return TRUE; } if ((firsttime) && (m == searchmap)) { i = searchtob+1; firsttime = FALSE; } else { i = 0; } for (; i < map[m].numtext; i++) { /* for each text object */ /* back to start - not found */ if ((m == searchmap) && (i == searchtob)) { searchwrap = FALSE; return TRUE; } /* does it contain the search string? */ if (strstr(map[m].textob[i].text, searchtext)) { drillto(m); map[m].selecteditemtype = T_TEXT; map[m].selecteditem = i; searchmap = m; searchtob = i; searchwrap = FALSE; return FALSE; } } numtextfound += (map[m].numtext); } return TRUE; } void drawarrowhead(SDL_Surface *screen, double x1, double y1, double x2, double y2, SDL_Color c, int arrowstyle, int arrowpos) { double angle; int arrowpointx,arrowpointy; int arrowend1x,arrowend1y; int arrowend2x,arrowend2y; int middlex, middley; int arrowlength = 5; int arrowthickness; arrowthickness = (arrowstyle & 0x0000ff); /* calculate arrow length based on line length line length > 40 means arrow length is 5, otherwise it's 3 */ //if (numpixels > 40) { // arrowlength = 5; //} else { arrowlength = 3; //} /* adjust for line thickness */ arrowlength = arrowlength + arrowthickness - 1; /* calculate angle of line */ angle = atan2(y2-y1,x2-x1); if (arrowpos == AP_START) { middlex = x1; middley = y1; } else { middlex = x2; middley = y2; } if (arrowpos == AP_END) { angle += M_PI; //if (angle > 360) angle -= 360; } angle = -angle; /* original arrowhead is: * * / (5,-5) * / * (0,0) < * \ * \ (5,5) */ /* rotate arrowhead */ arrowpointx = 0; arrowpointy = 0; arrowend1x = (arrowlength * cos(angle)) + (-arrowlength * sin(angle)); arrowend1y = (-arrowlength * sin(angle)) + (-arrowlength * cos(angle)); arrowend2x = (arrowlength * cos(angle)) + (arrowlength * sin(angle)); arrowend2y = (-arrowlength * sin(angle)) + (arrowlength * cos(angle)); /* translate arrowhead into position */ arrowpointx = middlex; arrowpointy = middley; arrowend1x += middlex; arrowend1y += middley; arrowend2x += middlex; arrowend2y += middley; /* get rid of the 'linestyle' and 'arrow' parts of arrowstyle to * (respectively) make sure the arrow looks okay and * avoid an infinite loop! */ arrowstyle &= 0x0000ff; drawline(screen, arrowpointx, arrowpointy, arrowend1x, arrowend1y, c, arrowstyle); drawline(screen, arrowpointx, arrowpointy, arrowend2x, arrowend2y, c, arrowstyle); } void drawarrowheadSVG(double x1, double y1, double x2, double y2, SDL_Color c, int arrowstyle, int arrowpos) { double angle; int arrowpointx,arrowpointy; int arrowend1x,arrowend1y; int arrowend2x,arrowend2y; int middlex, middley; int arrowlength = 5; int arrowthickness; arrowthickness = (arrowstyle & 0x0000ff); //if (numpixels > 40) { // arrowlength = 5; //} else { arrowlength = 3; //} /* adjust for line thickness */ arrowlength = arrowlength + arrowthickness - 1; /* calculate angle of line */ angle = atan2(y2-y1,x2-x1); if (arrowpos == AP_START) { middlex = x1; middley = y1; } else { middlex = x2; middley = y2; } if (arrowpos == AP_END) { angle += M_PI; //if (angle > 360) angle -= 360; } angle = -angle; /* original arrowhead is: * * / (5,-5) * / * (0,0) < * \ * \ (5,5) */ /* rotate arrowhead */ arrowpointx = 0; arrowpointy = 0; arrowend1x = (arrowlength * cos(angle)) + (-arrowlength * sin(angle)); arrowend1y = (-arrowlength * sin(angle)) + (-arrowlength * cos(angle)); arrowend2x = (arrowlength * cos(angle)) + (arrowlength * sin(angle)); arrowend2y = (-arrowlength * sin(angle)) + (arrowlength * cos(angle)); /* translate arrowhead into position */ arrowpointx = middlex; arrowpointy = middley; arrowend1x += middlex; arrowend1y += middley; arrowend2x += middlex; arrowend2y += middley; /* get rid of the 'linestyle' and 'arrow' parts of arrowstyle to * (respectively) make sure the arrow looks okay and * avoid an infinite loop! */ arrowstyle &= 0x000000ff; sprintf(svgbuf,"\n", arrowpointx, arrowpointy, arrowend1x, arrowend1y,c.r,c.g,c.b, arrowstyle ); fprintf(svgfile, svgbuf); sprintf(svgbuf,"\n", arrowpointx, arrowpointy, arrowend2x, arrowend2y,c.r,c.g,c.b, arrowstyle ); fprintf(svgfile, svgbuf); } void lerp(int *newx, int *newy, int ax, int ay, int bx, int by, float t) { *newx = ax + (bx - ax) * t; *newy = ay + (by - ay) * t; } void drawbezier(SDL_Surface *screen, int x1, int y1, int x2,int y2, int x3,int y3, int x4,int y4, SDL_Color c) { int i; float t; int abx,aby,bcx,bcy,cdx,cdy; int abbcx,abbcy,bccdx,bccdy; int newx,newy; int oldx,oldy; oldx = x1; oldy = y1; for (i = 0; i < BEZIERQUALITY; i++) { t = (float)i / (float)(BEZIERQUALITY - 1); lerp(&abx,&aby, x1, y1, x2, y2, t); lerp(&bcx,&bcy, x2, y2, x3, y3, t); lerp(&cdx,&cdy, x3, y3, x4, y4, t); lerp(&abbcx,&abbcy, abx, aby, bcx, bcy, t); lerp(&bccdx,&bccdy, bcx, bcy, cdx, cdy, t); lerp(&newx,&newy, abbcx, abbcy, bccdx, bccdy, t); drawline(screen, oldx, oldy, newx, newy, c, 1); oldx = newx; oldy = newy; } } void drawbox(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c, SDL_Color *fc) { if (fc != NULL) { if (fc->unused & USECOLOUR) { /* fill */ if (((x2 - x1) >= 2) && ((y2 - y1) >= 2)) { int y; for (y = (y1+1) ; y <= (y2-1); y++) { drawline(screen, x1+1, y, x2-1,y,*fc,1); } } } } drawline(screen,x1,y1,x2,y1,c,1); drawline(screen,x1,y1,x1,y2,c,1); drawline(screen,x1,y2,x2,y2,c,1); drawline(screen,x2,y1,x2,y2,c,1); } void drawellipsepoints(SDL_Surface *screen, int x1, int y1, int x, int y, SDL_Color c) { drawpixel(screen, x1 + x, y1 + y, c); drawpixel(screen, x1 - x, y1 + y, c); drawpixel(screen, x1 - x, y1 - y, c); drawpixel(screen, x1 + x, y1 - y, c); } void drawellipse(SDL_Surface *screen, int x1, int y1, int xr, int yr, SDL_Color c) { double x,y; double xc,yc; double ee; double twoas, twobs; double stoppingx,stoppingy; twoas = 2 * xr * xr; twobs = 2 * yr * yr; /* first set */ x = xr; y = 0; xc = yr * yr * (1 - 2*xr); yc = xr * xr; ee = 0; stoppingx = twobs * xr; stoppingy = 0; while (stoppingx >= stoppingy) { drawellipsepoints(screen, x1, y1, x,y, c); y++; stoppingy += twoas; ee += yc; yc += twoas; if ((2*ee + xc) > 0) { x--; stoppingx -= twobs; ee += xc; xc += twobs; } } /* second set */ x = 0; y = yr; xc = yr * yr; yc = xr * xr * (1 - 2*yr); ee = 0; stoppingx = 0; stoppingy = twoas * yr; while (stoppingx <= stoppingy) { drawellipsepoints(screen, x1, y1, x,y, c); x++; stoppingx += twobs; ee += xc; xc += twobs; if ((2*ee + yc) > 0) { y--; stoppingy -= twoas; ee += yc; yc += twoas; } } } void drawflowbox(SDL_Surface *dest, int oid, int otype) { int x1,y1,x2,y2; int i; int ls = 10; switch (otype) { case T_OBJECT: x1 = map[curmap].obj[oid].x; y1 = map[curmap].obj[oid].y; x2 = map[curmap].obj[oid].x + map[curmap].obj[oid].w; y2 = map[curmap].obj[oid].y + map[curmap].obj[oid].h; drawbox(dest, x1, y1, x2, y2, blue, NULL); break; case T_LINK: x1 = map[curmap].obj[map[curmap].olink[oid].srcobj].x + map[curmap].olink[oid].srcxoff; y1 = map[curmap].obj[map[curmap].olink[oid].srcobj].y + map[curmap].olink[oid].srcyoff; x2 = map[curmap].obj[map[curmap].olink[oid].dstobj].x + map[curmap].olink[oid].dstxoff; y2 = map[curmap].obj[map[curmap].olink[oid].dstobj].y + map[curmap].olink[oid].dstyoff; drawbox(dest, x1-ls, y1-ls, x1+ls, y1+ls, blue, &blue); drawbox(dest, x2-ls, y2-ls, x2+ls, y2+ls, blue, &blue); for (i = 0; i < map[curmap].olink[oid].npoints; i++) { x1 = map[curmap].olink[oid].point[i].x; y1 = map[curmap].olink[oid].point[i].y; drawbox(dest, x1-ls, y1-ls, x1+ls, y1+ls, blue, &blue); } break; case T_TEXT: if (map[curmap].textob[oid].anchor == -1) { x1 = map[curmap].textob[oid].x; y1 = map[curmap].textob[oid].y; } else { x1 = map[curmap].textob[oid].x + map[curmap].obj[map[curmap].textob[oid].anchor].x; y1 = map[curmap].textob[oid].y + map[curmap].obj[map[curmap].textob[oid].anchor].y; } x2 = x1 + map[curmap].textob[oid].w; y2 = y1 + map[curmap].textob[oid].h; drawbox(dest, x1, y1, x2, y2, blue, NULL); break; default: return; } } void drawcolorchart(SDL_Surface *dest) { int x,y; //int i; SDL_Color c; int speed; int finished = FALSE; int size = 18; int mode = 1; c.r = 0; c.g = 0; c.b = 0; c.unused = USECOLOUR; 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, &c); /* fill box */ /*for (i = 1; i <= (size-2); i++) { drawline(dest, x+1, y+i, x+(size-2), y+i, c,1); }*/ /* change color */ if (mode == 1) { if (c.b + speed > 255) { c.b = 0; if (c.g + speed > 255) { c.g = 0; if (c.r + speed > 255) { c.r = 255 - speed; c.g = 255 - speed; c.b = 255 - speed; mode = 2; } else c.r += speed; } else c.g += speed; } else c.b += speed; } else { if (c.r-speed <= 0) finished = TRUE; if (c.g-speed <= 0) finished = TRUE; if (c.b-speed <= 0) finished = TRUE; c.r -= speed; c.g -= speed; 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 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 linestyle) { int deltax, deltay; int numpixels; int d; int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; int i; int x; int y; int xx,yy; int maskcount = 0; int maskindex = 0; Uint8 arrow,style, thickness; arrow = (linestyle & (0x00ff0000)) >> 16; style = (linestyle & (0x0000ff00)) >> 8; thickness = (linestyle & (0x000000ff)); 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; maskcount = 0; maskindex = 0; for (i = 0; i < numpixels; i++) { if (linemask[style][maskindex] == 1) { /* plot point */ for (yy = 0; yy < thickness ; yy++) { for (xx = 0; xx < thickness ; xx++) { drawpixel(screen,x+xx,y+yy,c); } } } /* increment mask count */ if (++maskcount >= thickness) { maskcount = 0; /* increment mask index */ maskindex++; if (maskindex >= LINESTYLESIZE) { maskindex = 0; } if (linemask[style][maskindex] == -1) maskindex = 0; } if (d < 0) { d += dinc1; x += xinc1; y += yinc1; } else { d += dinc2; x += xinc2; y += yinc2; } } /* draw arrowheads if required */ if (arrow) { if ((arrow == AP_START) || (arrow == AP_END)) { drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, arrow); } else if (arrow == AP_BOTH) { drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, AP_START); drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, AP_END); } } } void drawlink(SDL_Surface *dest, link_t *l) { int i; int x,y,x2,y2; int arrow; int adjx,adjy; int flow; flow = l->col.unused & ISFLOW; x = map[curmap].obj[l->srcobj].x + l->srcxoff - screenx; y = map[curmap].obj[l->srcobj].y + l->srcyoff - screeny; arrow = (l->style & 0x00ff0000) >> 16; for (i = 0; i < l->npoints; i++) { x2 = l->point[i].x - screenx; y2 = l->point[i].y - screeny; /* if this is the first point and the line is of type "arrowhead at start" then draw an arrow */ if ( (i == 0) && ((arrow == AP_START) || (arrow == AP_BOTH)) ) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_START << 16); /* adjust start point */ if (flow) { adjx = x; adjy = y; } else { adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); } drawline(dest, adjx,adjy,x2,y2, l->col,tempstyle); } else { /* clear the "arrowhead" part of these */ adjx = x; adjy = y; drawline(dest, adjx,adjy,x2,y2, l->col,l->style & 0xff00ffff); } x = x2; y = y2; } /* draw line to final map[curmap].object */ x2 = map[curmap].obj[l->dstobj].x + l->dstxoff - screenx; y2 = map[curmap].obj[l->dstobj].y + l->dstyoff - screeny; /* adjust end */ if (l->npoints >= 1) { if ( (arrow == AP_END) || (arrow == AP_BOTH)) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_END << 16); if (!flow) { adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_END); x2 = adjx ; y2 = adjy; } drawline(dest, x,y,x2,y2, l->col,tempstyle); } else { /* clear the "arrowhead" part of these */ drawline(dest, x,y,x2,y2, l->col,l->style & 0xff00ffff); } } else { /* adjust start */ if (!flow) { if ((arrow == AP_START) || (arrow == AP_BOTH)) { adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_START); x = adjx ; y = adjy; } } /* adjust end */ if (!flow) { if ((arrow == AP_END) || (arrow == AP_BOTH)) { adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_END); x2 = adjx ; y2 = adjy; } } drawline(dest, x,y,x2,y2, l->col,l->style); } } void drawlinkSVG(link_t *l) { int i; int x,y,x2,y2; int width; char temp[BUFLEN]; char dasharray[BUFLEN]; int linestyle; int cur,old; int count; int first; int arrow; int adjx,adjy; int flow; x = map[curmap].obj[l->srcobj].x + l->srcxoff; y = map[curmap].obj[l->srcobj].y + l->srcyoff; flow = l->col.unused & ISFLOW; /* get attributes */ width = l->style & 0x000000ff; linestyle = (l->style & 0x0000ff00) >> 8; arrow = (l->style & 0x00ff0000) >> 16; old = linemask[linestyle][0]; count = 1; first = 1; sprintf(dasharray, "stroke-dasharray:"); for (i = 0; linemask[linestyle][i] != -1; i++) { cur = linemask[linestyle][i]; //sprintf(temp, "[%d]", cur); //strcat(dasharray, temp); if (cur == old) { count++; } else { if (first) { sprintf(temp, "%d", count*width); first = 0; } else { sprintf(temp, ",%d", count*width); } count = 1; strcat(dasharray, temp); old = cur; } } if (first == 1) { /* don't need dash-array */ strcpy(dasharray, ""); } else { sprintf(temp, ",%d", count*width); strcat(dasharray, temp); } for (i = 0; i < l->npoints; i++) { x2 = l->point[i].x; y2 = l->point[i].y; sprintf(svgbuf,"\n", x, y, x2, y2,l->col.r,l->col.g,l->col.b, width ,dasharray); fprintf(svgfile, svgbuf); /* draw arrowhead if required */ if ( (i == 0) && ((arrow == AP_START) || (arrow == AP_BOTH)) ) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_START << 16); if (flow) { adjx = x; adjy = y; } else { adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); } drawarrowheadSVG(adjx,adjy,x2,y2, l->col,tempstyle, arrow); } 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; /* draw arrow if required */ if (l->npoints >= 1) { if ( (arrow == AP_END) || (arrow == AP_BOTH)) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_END << 16); if (!flow) { adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_END); x2 = adjx; y2 = adjy; } drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_END); } } else { /* adjust start point too */ if ( (arrow == AP_START) || (arrow == AP_BOTH)) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_START << 16); if (!flow) { adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); x = adjx; y = adjy; } drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_START); } if ( (arrow == AP_END) || (arrow == AP_BOTH)) { int tempstyle; tempstyle = l->style & (0xff00ffff); tempstyle |= (AP_END << 16); if (!flow) { adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_END); x2 = adjx; y2 = adjy; } drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_END); } } sprintf(svgbuf,"\n", x, y, x2, y2,l->col.r,l->col.g,l->col.b, width ,dasharray); fprintf(svgfile, svgbuf); } void drawobject(SDL_Surface *dest, mapobject_t *o, int doublebuffer, int adjust) { SDL_Surface *temps; SDL_Rect area; Uint32 bgcol; int testing = 0; /* create temp surface */ if (testing) { printf("About to create surface..."); fflush(STDOUT); } if (doublebuffer) { 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); } else { temps = dest; } 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 */ if (testing) { printf("About to drawvector ..."); fflush(STDOUT); } if (o->fillcol.unused & USECOLOUR) { drawvector(temps, &objtype[o->type].vimg, 0, 0, o->w, o->h, NULL, &o->fillcol); } else { drawvector(temps, &objtype[o->type].vimg, 0, 0, o->w, o->h, NULL, NULL); } /* set transparent colour on temp surface */ if (testing) { printf("About to setcolour ..."); fflush(STDOUT); } SDL_SetColorKey(temps, SDL_SRCCOLORKEY|SDL_RLEACCEL, bgcol); /* blit to screen */ if (doublebuffer) { area.x = o->x; area.y = o->y; if (adjust) { area.x -= screenx; area.y -= screeny; } area.w = o->w; area.h = o->h; if (testing) { printf("About to blitsurface ..."); fflush(STDOUT); } SDL_BlitSurface(temps, 0, dest, &area); SDL_FreeSurface(temps); temps = NULL; } else { SDL_UpdateRect(temps, 0, 0, o->w, o->h); } if (testing) { printf("About to return ..."); fflush(STDOUT); } } void drawobjectSVG(SDL_Surface *dest, mapobject_t *o, int doublebuffer) { static int gnum = 0; /* create SVG group */ sprintf(svgbuf, "\n", gnum); fprintf(svgfile, svgbuf); if (o->fillcol.unused & USECOLOUR) { drawvectorSVG(&objtype[o->type].vimg, o->x, o->y, o->w, o->h, NULL, &o->fillcol); } else { drawvectorSVG(&objtype[o->type].vimg, o->x, o->y, o->w, o->h, NULL, NULL); } sprintf(svgbuf, "\n"); fprintf(svgfile, svgbuf); gnum++; } 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 ((x < 0) || (y < 0) || (x >= screen->w) || (y >= screen->h)) { return; } /*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(int wantdecs) { int i; int testing = 0; SDL_Rect area; Uint32 fillcol; int txoff,tyoff; int anchoreditem; int x,y; for (i = 0; i < map[curmap].numthings; i++) { thingdrawn[i] = FALSE; } if ((state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING) || (state == S_SEARCH)) { /* show text entry screen */ showfiledialog(); return; } if ((state == S_FGCOL) || (state == S_FILLCOL)) { drawcolorchart(screen); return; } if (state == S_CREATETELE) { drawmaplist(screen); return; } if (state == S_REALLYQUIT) { drawyn(text); return; } if (testing) { printf("START DRAWMAP\n"); fflush(STDOUT); } /* 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 grid */ if (gridsize != 0) { for (x = 0; x < screen->w - SIDEBARW; x += (gridsize*2)) { drawline(buffer,x,0,x,(screen->h - STATUSH), gridcol, (LS_BIGDASH << 8) | 1); if ((x+gridsize) < screen->w - SIDEBARW) { drawline(buffer,x+gridsize,0,x+gridsize,(screen->h - DEFTEXTH-2), gridcol, (LS_DOTTED << 8) | 1); } } for (y = 0; y < screen->h - STATUSH; y += (gridsize*2)) { drawline(buffer,0,y,screen->w - SIDEBARW, y,gridcol, (LS_BIGDASH << 8) | 1); if ((y+gridsize) < (screen->h - STATUSH)) { drawline(buffer,0,y+gridsize,screen->w - SIDEBARW, y+gridsize,gridcol, (LS_DOTTED << 8) | 1); } } } if (testing) { printf("DRAWING THINGS \n"); fflush(STDOUT); } /* draw all map[curmap].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); } if (!isflow(map[curmap].thing[i].id, T_OBJECT)) { drawobject(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE, TRUE); thingdrawn[i] = TRUE; } } 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); } if (!isflow(map[curmap].thing[i].id, T_LINK)) { drawlink(buffer, &map[curmap].olink[map[curmap].thing[i].id]); thingdrawn[i] = TRUE; } } 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); } if (!isflow(map[curmap].thing[i].id, T_TEXT)) { drawtext(buffer, &map[curmap].textob[map[curmap].thing[i].id], TRUE); thingdrawn[i] = TRUE; } } else { printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type); thingdrawn[i] = TRUE; } } /* show traffic flows (these should be on top of everything else) */ if (showflows) { for (i = 0; i < map[curmap].numthings; i++) { if (map[curmap].thing[i].type == T_OBJECT) { if (isflow(map[curmap].thing[i].id, T_OBJECT)) { drawobject(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE, TRUE); if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_OBJECT); thingdrawn[i] = TRUE; } } else if (map[curmap].thing[i].type == T_LINK) { if (isflow(map[curmap].thing[i].id, T_LINK)) { drawlink(buffer, &map[curmap].olink[map[curmap].thing[i].id]); if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_LINK); thingdrawn[i] = TRUE; } } else if (map[curmap].thing[i].type == T_TEXT) { if (isflow(map[curmap].thing[i].id, T_TEXT)) { drawtext(buffer, &map[curmap].textob[map[curmap].thing[i].id], TRUE); if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_TEXT); thingdrawn[i] = TRUE; } } } } if (testing) { printf("FINISHED THINGS \n"); fflush(STDOUT); } if (testing) { printf("DRAWING HIGHLIGHT\n"); fflush(STDOUT); } /* highlight the selected map[curmap].object */ /* by drawing boxes in its corners */ if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_OBJECT) { int n; /* 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 - screenx; area.y = map[curmap].obj[map[curmap].selecteditem].y - screeny; 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 - screenx; area.y = map[curmap].obj[map[curmap].selecteditem].y - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom left */ area.x = map[curmap].obj[map[curmap].selecteditem].x - screenx; area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h - screeny; 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 - screenx; area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h - screeny; SDL_FillRect(buffer, &area, fillcol); /* Also highlight any text anchored to this object */ for (n = 0; n < map[curmap].numtext; n++) { if (map[curmap].textob[n].anchor == map[curmap].selecteditem) { int th; /* calculate text's height */ th = TTF_FontHeight(font[map[curmap].textob[n].h]); /* 10% of text's size */ area.w = map[curmap].textob[n].w / OBJSELHANDLEPCT; area.h = th / OBJSELHANDLEPCT; if (area.w < 2) area.w = 2; if (area.h < 2) area.h = 2; anchoreditem = map[curmap].textob[n].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, 255, 0); /* top left */ area.x = map[curmap].textob[n].x + txoff - screenx; area.y = map[curmap].textob[n].y + tyoff - screeny; SDL_FillRect(buffer, &area, fillcol); /* top right */ area.x = map[curmap].textob[n].x +txoff + map[curmap].textob[n].w - area.w - screenx; area.y = map[curmap].textob[n].y + tyoff - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom left */ area.x = map[curmap].textob[n].x +txoff - screenx; area.y = map[curmap].textob[n].y + tyoff + th - area.h - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom right */ area.x = map[curmap].textob[n].x+txoff + map[curmap].textob[n].w - area.w - screenx; area.y = map[curmap].textob[n].y +tyoff+ th - area.h - screeny; SDL_FillRect(buffer, &area, fillcol); } } } else if (map[curmap].selecteditemtype == T_TEXT) { int th; /* calculate text's height */ th = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); /* 10% of text's size */ area.w = map[curmap].textob[map[curmap].selecteditem].w / OBJSELHANDLEPCT; area.h = th / 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 - screenx; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff - screeny; 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 - screenx; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom left */ area.x = map[curmap].textob[map[curmap].selecteditem].x +txoff - screenx; area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff + th - area.h - screeny; 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 - screenx; area.y = map[curmap].textob[map[curmap].selecteditem].y +tyoff+ th - area.h - screeny; 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 - screenx; area.y = map[curmap].obj[anchoreditem].y - screeny; SDL_FillRect(buffer, &area, fillcol); /* top right */ area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w - screenx; area.y = map[curmap].obj[anchoreditem].y - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom left */ area.x = map[curmap].obj[anchoreditem].x - screenx; area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h - screeny; SDL_FillRect(buffer, &area, fillcol); /* bottom right */ area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w - screenx; area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h - screeny; 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) - screenx; area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2) - screeny; 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) - screenx; area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2) - screeny; 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) - screenx; area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2) - screeny; 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) - screenx; area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2) - screeny; 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) - screenx; area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2) - screeny; 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) - screenx; area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2) - screeny; SDL_FillRect(buffer, &area, fillcol); } } } /* blit buffer to screen */ SDL_BlitSurface(buffer, 0, screen,0); if (testing) { printf("START MAPBOX\n"); fflush(STDOUT); } drawmapbox(); /* draw status bar */ if (wantdecs) { if (testing) { printf("START STATUSBAR\n"); fflush(STDOUT); } drawstatusbar(); } if (testing) { printf("FLIP\n"); fflush(STDOUT); } if (wantdecs) { /* draw scrollbars, if required */ if (map[curmap].width > (screen->w - SIDEBARW)) { drawxscrollbar(); } if (map[curmap].height > (screen->h - STATUSH)) { drawyscrollbar(); } } /* calculate mapdimensions if diagram has been modified */ if (needtocalc) { calcmapdimensions(); needtocalc = FALSE; } /* flip */ SDL_Flip(screen); //SDL_UpdateRect(screen, 0, 0, map[curmap].width, map[curmap].height); } void drawxscrollbar(void) { int barw; double barx; barx = ((double)screenx / (double)map[curmap].width) * (screen->w - SIDEBARW - SBSIZE); /* scrollbar outline */ drawbox(screen, 0, screen->h - STATUSH - SBSIZE, screen->w - SIDEBARW - SBSIZE, screen->h - STATUSH - 1, blue2 , &blue2); /* screen position */ barw = (((double)(screen->w - SIDEBARW - SBSIZE) / (double)map[curmap].width) * (screen->w - SIDEBARW - SBSIZE)); if (barx+barw > (screen->w - SIDEBARW-SBSIZE)) barw = screen->w - SIDEBARW - SBSIZE - barx; drawbox(screen, barx, screen->h - STATUSH - SBSIZE+1, barx + barw, screen->h - STATUSH - 2, blue , &blue); SDL_UpdateRect(screen, 0,screen->h - STATUSH - SBSIZE, screen->w, SBSIZE); } void drawyscrollbar(void) { int barh; double bary; bary = ((double)screeny / (double)map[curmap].height) * (screen->h - STATUSH - SBSIZE); /* scrollbar outline */ drawbox(screen, screen->w - SIDEBARW - SBSIZE, 0, screen->w - SIDEBARW - 2, screen->h - STATUSH - SBSIZE - 1, blue2, &blue2); /* screen position */ barh = (((double)(screen->h - STATUSH - SBSIZE) / (double)map[curmap].height) * (screen->h - STATUSH - SBSIZE)); if (bary+barh > (screen->h - STATUSH - SBSIZE)) barh = screen->h - STATUSH - SBSIZE - bary; drawbox(screen, screen->w - SIDEBARW - SBSIZE+1, bary, screen->w - SIDEBARW - 3, bary + barh, blue , &blue); SDL_UpdateRect(screen, screen->w - SIDEBARW - SBSIZE, 0, SBSIZE, screen->h - STATUSH - SBSIZE - 1); } void validatescreenpos(void) { if (screenx + (screen->w - SIDEBARW) > map[curmap].width) { screenx = map[curmap].width - (screen->w - SIDEBARW); } if (screenx < 0) screenx = 0; if (screeny + (screen->h - STATUSH) > map[curmap].height) { screeny = map[curmap].height - (screen->h - STATUSH); } if (screeny < 0) screeny = 0; } void drawsearchflash(void) { SDL_Surface *temps; SDL_Rect area; int txoff,tyoff; int anchoreditem; if (!searchflash) { return; } /* highlight the object just found in a search */ if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_TEXT) { int th; /* calculate text's height */ th = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); area.w = map[curmap].textob[map[curmap].selecteditem].w; area.h = th; 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; } area.x = map[curmap].textob[map[curmap].selecteditem].x - screenx + txoff; area.y = map[curmap].textob[map[curmap].selecteditem].y - screeny + tyoff; /* restore background */ SDL_BlitSurface(searchbg, NULL, screen, &area); /* draw hilight */ temps = SDL_CreateRGBSurface(SDL_SWSURFACE,area.w, area.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); SDL_FillRect(temps, 0, SDL_MapRGB(temps->format, 0, 0, 255)); SDL_SetColorKey(temps, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(temps->format, 255, 255, 255)); SDL_SetAlpha(temps, SDL_SRCALPHA, searchflash); SDL_BlitSurface(temps, NULL, screen, &area); SDL_FreeSurface(temps); SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } } } void drawstatusbar(void) { Uint32 col; SDL_Rect area; if (errorflash) { statusbarcolour.r = 255; statusbarcolour.g = 255 - errorflash; statusbarcolour.b = 255 - errorflash; } else if (infoflash) { statusbarcolour.r = 255 - infoflash; statusbarcolour.g = 255; statusbarcolour.b = 255 - infoflash; } /* clear it */ /*col = SDL_MapRGB(screen->format, map[curmap].bgcol.r, map[curmap].bgcol.g, map[curmap].bgcol.b);*/ col = SDL_MapRGB(screen->format, statusbarcolour.r, statusbarcolour.g, statusbarcolour.b); area.x = 0; area.y = screen->h - STATUSH; area.w = screen->w - SIDEBARW; area.h = DEFTEXTH + 4; SDL_FillRect(screen, &area, col); if ((errorflash) || (infoflash)) { statusbarcolour.r = 255; statusbarcolour.g = 255; statusbarcolour.b = 255; } drawline(screen, 0, screen->h - STATUSH, screen->w - SIDEBARW, screen->h - STATUSH, blue,1); /* strip newlines from text */ if (statustext[strlen(statustext)-1] == '\n') statustext[strlen(statustext)-1] = '\0'; drawtextat(screen, 2, screen->h - DEFTEXTH-2, statustext, DEFTEXTH, black); /* show modified status */ if (modified) { int tw,th; /* calculate width */ TTF_SizeText(font[DEFTEXTH-1], "MOD", &tw,&th); drawbox(screen, screen->w - SIDEBARW-33,screen->h - STATUSH+1, screen->w - SIDEBARW-30+tw+1,screen->h - STATUSH+2+th,blue, NULL); drawtextat(screen, screen->w - SIDEBARW-30, screen->h - DEFTEXTH - 2, "MOD", DEFTEXTH-1, blue); } /* show readonly status */ if (readonly) { int tw,th; TTF_SizeText(font[DEFTEXTH-1], "RO", &tw,&th); /* same place as 'mod' box, as in readonly mode map can't be modified */ drawbox(screen, screen->w - SIDEBARW-33,screen->h - STATUSH+1, screen->w - SIDEBARW-30+tw+1,screen->h - STATUSH+2+th,blue, NULL); drawtextat(screen, screen->w - SIDEBARW-30, screen->h - DEFTEXTH - 2, "RO", DEFTEXTH-1, blue); } SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } int drawSVG(char *svgfilename) { int i; if (startSVG(svgfilename)) { return TRUE; } /* draw all map[curmap].objects links etc*/ for (i = 0; i < map[curmap].numthings; i++) { if (map[curmap].thing[i].type == T_OBJECT) { if (!isflow(map[curmap].thing[i].id, T_OBJECT)) { drawobjectSVG(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE); } } else if (map[curmap].thing[i].type == T_LINK) { if (!isflow(map[curmap].thing[i].id, T_LINK)) { drawlinkSVG(&map[curmap].olink[map[curmap].thing[i].id]); } } else if (map[curmap].thing[i].type == T_TEXT) { if (!isflow(map[curmap].thing[i].id, T_TEXT)) { drawtextSVG(&map[curmap].textob[map[curmap].thing[i].id]); } } else { printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type); } } /* show traffic flows (these should be on top of everything else) */ if (showflows) { for (i = 0; i < map[curmap].numthings; i++) { if (map[curmap].thing[i].type == T_OBJECT) { if (isflow(map[curmap].thing[i].id, T_OBJECT)) { drawobjectSVG(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE); } } else if (map[curmap].thing[i].type == T_LINK) { if (isflow(map[curmap].thing[i].id, T_LINK)) { drawlinkSVG(&map[curmap].olink[map[curmap].thing[i].id]); } } else if (map[curmap].thing[i].type == T_TEXT) { if (isflow(map[curmap].thing[i].id, T_TEXT)) { drawtextSVG(&map[curmap].textob[map[curmap].thing[i].id]); } } } } endSVG(); return FALSE; } void drawmapbox(void) { text_t temp; int x,y; int i; int lh = MAPBOXTEXTHEIGHT; int found; int n; Uint32 fillcol; SDL_Rect area; int tw,th; char temptext[BUFLEN]; int changed; int donesomething; char name1[BUFLEN], name2[BUFLEN]; 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); /* determine size of each row in pixels (and the width of the title) */ strcpy(temptext, map[curmap].name); TTF_SizeText(font[lh], temptext, &tw,&th); /* truncate name until it will fit */ changed = FALSE; while (tw >= mapbox.width) { if (changed) { /* change last char to ".." */ temptext[strlen(temptext)-1] = '\0'; strcat(temptext, ".."); changed = TRUE; } else { /* change 3rd last char to '.', and lose 1 char off end */ temptext[strlen(temptext)-3] = '.'; temptext[strlen(temptext)-1] = '\0'; } TTF_SizeText(font[lh], temptext, &tw,&th); } /* box around edge */ drawbox(screen, mapbox.x, mapbox.y, mapbox.x + mapbox.width-2,mapbox.y + mapbox.height,white, NULL); drawbox(screen, mapbox.x+1, mapbox.y+1, mapbox.x + mapbox.width-3,mapbox.y + th,white, &white); /* current map */ /* centre this inside the map box */ drawtextat(screen, (x+((mapbox.width-3)/2) - (tw/2)), y, temptext, lh, black); y += th; /* seperator line */ drawline(screen, x, y, x+mapbox.width-2, y, white,1); y++; /* show .. */ if (numhistory >= 1) { /* draw back arrow */ drawline(screen, x+5,y+(lh/2),x+mapbox.width-15,y+(lh/2),white,1); drawline(screen, x+5,y+(lh/2),x+15,y+1,white,1); drawline(screen, x+5,y+(lh/2),x+15,y+(lh-1),white,1); } y += th; /* children ... */ /* first generate list of 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) { children[numchildren] = map[curmap].obj[i].child; numchildren++; } } } /* sort the list */ donesomething = TRUE; while (donesomething) { donesomething = FALSE; for (i = 0; i < (numchildren-1); i++) { /* get name of this one */ strcpy(name1, ""); strcpy(name2, ""); for (n = 0; n < map[curmap].numobjects; n++) { if (!strcmp(name1, "")) { if (map[curmap].obj[n].child == children[i]) { sprintf(name1, map[map[curmap].obj[n].child].name); } } if (!strcmp(name2, "")) { if (map[curmap].obj[n].child == children[i+1]) { sprintf(name2, map[map[curmap].obj[n].child].name); } } } if (strcmp(name1, name2) > 0) { int tempnum; /* swap them */ tempnum = children[i]; children[i] = children[i+1]; children[i+1] = tempnum; donesomething = TRUE; } } } /* now draw all children, starting at mapbox.offset */ for (i = mapbox.offset; i < numchildren; i++) { if ((i == mapbox.offset) && (mapbox.offset > 0)) { /* replace this entry with an arrow */ children[i] = C_SCROLLUP; /* draw an up arrow */ TTF_SizeText(font[lh], "unused", &tw,&th); drawline(screen, x + (mapbox.width / 2)-3, y+th-4, x + (mapbox.width / 2), y+th-7, white, 1); drawline(screen, x + (mapbox.width / 2)+3, y+th-4, x + (mapbox.width / 2), y+th-7, white, 1); } else { /* get its name */ sprintf(temp.text, "*Unknown*"); /* default, shouldn't actually ever be used */ for (n = 0; n < map[curmap].numobjects; n++) { if (map[curmap].obj[n].child == children[i]) { sprintf(temp.text, map[map[curmap].obj[n].child].name); break; } } TTF_SizeText(font[lh], temp.text, &tw,&th); /* truncate name until it will fit */ changed = FALSE; while (tw >= mapbox.width) { if (changed) { /* change last char to ".." */ temp.text[strlen(temp.text)-1] = '\0'; strcat(temp.text, ".."); changed = TRUE; } else { /* change 3rd last char to '.', and lose 1 char off end */ temp.text[strlen(temp.text)-3] = '.'; temp.text[strlen(temp.text)-1] = '\0'; } TTF_SizeText(font[lh], temp.text, &tw,&th); } temp.x = x; temp.y = y; temp.h = lh; TTF_SizeText(font[lh], temp.text, &tw,&th); temp.w = tw; temp.anchor = -1; /* is this map already in our history? if so show it in a different colour */ if (isinhistory(children[i]) != -1) { temp.c = cyan; } else { temp.c = white; } if (temp.y + temp.h >= (mapbox.y + mapbox.height)) { SDL_Rect ar; /* off the bottom of the page - replace previous item with an arrow */ y = y - th - 1; /* go back one line */ /* clear previous text */ ar.x = x; ar.y = y; ar.w = mapbox.width - 3; ar.h = th; SDL_FillRect(screen, &ar, fillcol); /* draw arrow */ drawline(screen, x + (mapbox.width / 2)-3, y+th-7, x + (mapbox.width / 2), y+th-4, white, 1); drawline(screen, x + (mapbox.width / 2)+3, y+th-7, x + (mapbox.width / 2), y+th-4, white, 1); children[i-1] = C_SCROLLDOWN; break; } drawtext(screen, &temp, FALSE); } y += th; } 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; 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 = screen->w - SIDEBARW; area.h = screen->h - STATUSH; SDL_FillRect(screen, &area, fillcol); x = 10; y = 10; drawtextat(screen, x, y, "Select map to link to:", DEFTEXTH*2, black); y = 50; drawbox(dest, x, y, screen->w-SIDEBARW-1,y+(DEFTEXTH*2),blue, NULL); drawtextat(screen, x+1, y+1, "(none)", (DEFTEXTH*2)-2, blue); y += (DEFTEXTH*2); for (i = maplistpos; i < nummaps; i++) { drawbox(dest, x, y, screen->w-SIDEBARW-1,y+(DEFTEXTH*2),blue, NULL); drawtextat(dest, x+1, y+1, map[i].name, (DEFTEXTH*2)-2, blue); 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+4; 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++) { int n; if ((x + obox.gridsize) >= (screen->w)) { x = obox.x; if ((y + obox.gridsize) >= (screen->h)) { break; } y += obox.gridsize + 3; } /* draw box */ //outlinecol = obox.gridcol; drawline(screen, x, y,x+obox.gridsize,y,gridhigh,1); /* top */ drawline(screen, x, y+obox.gridsize,x+obox.gridsize,y+obox.gridsize,gridlow,1); /* bottom */ drawline(screen, x, y,x,y+obox.gridsize,gridhigh,1); /* left */ drawline(screen, x+obox.gridsize, y,x+obox.gridsize,y+obox.gridsize,gridlow,1); /* 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 object */ temp.type = i; temp.x = x+1; temp.y = y+1; temp.w = obox.gridsize-2; temp.h = obox.gridsize-2; temp.fillcol.r = 0; temp.fillcol.g = 0; temp.fillcol.b = 0; temp.fillcol.unused = 0; drawobject(screen, &temp, TRUE, FALSE); /* show keyboard shortcuts */ for (n = 0; n < shortcutnum; n++) { if (shortcut[n] == i) { SDL_Surface *ts; SDL_Rect area; char numtext[2]; int tw,th; SDL_Color fc = yellow; sprintf(numtext, "%d",n); ts = TTF_RenderText_Blended(font[SHORTCUTSIZE], numtext, blue); TTF_SizeText(font[SHORTCUTSIZE], numtext, &tw,&th); fc.unused |= USECOLOUR; drawbox(screen,x+2,y - 2 + (obox.gridsize) - SHORTCUTSIZE, x+2+tw, y + (obox.gridsize) - SHORTCUTSIZE + tw, yellow, &fc); area.x = x + 3; area.y = y + (obox.gridsize) - 4 - SHORTCUTSIZE; area.w = tw; area.h = th; SDL_BlitSurface(ts, 0, screen, &area); SDL_FreeSurface(ts); ts = NULL; } } //SDL_UpdateRect(screen, x, y, obox.gridsize+1,obox.gridsize+1); x += obox.gridsize+3; } /* 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+3) + obox.y; x = ((map[curmap].selectedtype - (obox.pos*3)) % obox.gridrowlen) * (obox.gridsize+3) + obox.x; drawline(screen, x, y,x+obox.gridsize,y,outlinecol,1); /* top */ drawline(screen, x, y+obox.gridsize,x+obox.gridsize,y+obox.gridsize,outlinecol,1); /* bottom */ drawline(screen, x, y,x,y+obox.gridsize,outlinecol,1); /* left */ drawline(screen, x+obox.gridsize, y,x+obox.gridsize,y+obox.gridsize,outlinecol,1); /* right */ } //SDL_UpdateRect(screen, x, y, obox.gridsize+1,obox.gridsize+1); // xxx remove //SDL_Flip(screen); SDL_UpdateRect(screen,obox.x, obox.y, obox.width-1, obox.height+5); } void drawscreen(void){ drawmap(TRUE); drawtoolbox(); drawobox(); SDL_Flip(screen); } void drawtext(SDL_Surface *dest, text_t *t, int adjust) { int tw,th; int txoff,tyoff; SDL_Rect area; SDL_Surface *ts; if (strlen(t->text) == 0) { return; } /* calculate letter width, letter height */ tw = t->w / strlen(t->text); 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; } if (th >= MAXLETTERHEIGHT) th = MAXLETTERHEIGHT-1; ts = TTF_RenderText_Blended(font[th], t->text, t->c); area.x = t->x + txoff; area.y = t->y + tyoff; area.w = t->w; area.h = t->h; if (adjust) { area.x -= screenx; area.y -= screeny; } SDL_BlitSurface(ts, 0, dest, &area); SDL_FreeSurface(ts); ts = NULL; } /* x or y == -1 means to centre */ void drawtextat(SDL_Surface *dest, int x, int y, char *text, int size, SDL_Color c) { int tw,th; text_t temp; sprintf(temp.text, text); temp.h = size; TTF_SizeText(font[size], temp.text, &tw,&th); temp.w = tw; if (x >= 0) { temp.x = x; } else { temp.x = ((screen->w-SIDEBARW) / 2) - (tw / 2); } if (y >= 0) { temp.y = y; } else { temp.y = ((screen->h-STATUSH) / 2) - (th / 2); } temp.c.r = c.r; temp.c.g = c.g; temp.c.b = c.b; temp.anchor = -1; drawtext(dest, &temp, FALSE); } char *fixforhtml(char *oldtext, char *newtext) { char *p, *p2; p2 = newtext; for (p = oldtext ; *p ; p++) { switch (*p) { case '&': *p2 = '\0'; strcat(p2, "&"); p2 += strlen("&"); break; case '"': *p2 = '\0'; strcat(p2, """); p2 += strlen("""); break; case '<': *p2 = '\0'; strcat(p2, "<"); p2 += strlen("<"); break; case '>': *p2 = '\0'; strcat(p2, ">"); p2 += strlen(">"); break; default: *p2 = *p; p2++; break; } } *p2 = '\0'; return newtext; } void drawtextSVG(text_t *t) { int tw,th; int txoff,tyoff; char newtext[BUFLEN]; if (strlen(t->text) == 0) { return; } /* calculate letter width, letter height */ tw = t->w / strlen(t->text); 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; } if (th >= MAXLETTERHEIGHT) th = MAXLETTERHEIGHT-1; /* have to add text pixel height here, cause SVG measures from bottom left of text - netmapr measures from top left */ sprintf(svgbuf, "\n", t->x + txoff, t->y + tyoff + t->h, t->h, t->c.r, t->c.g, t->c.b); fprintf(svgfile, svgbuf); fixforhtml(t->text, newtext); sprintf(svgbuf, "%s\n\n",newtext); fprintf(svgfile, svgbuf); } void drawtoolbox(void) { int x,y,i; SDL_Rect area; Uint32 fillcol; Uint32 bcol; int z; if (oldselection >= 0) dontpaste = TRUE; 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) >= (screen->w)) { 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,1); /* top */ drawline(screen, x, y+1,x+toolbox.gridsize,y+1,gridhigh,1); /* top */ drawline(screen, x, y+toolbox.gridsize-1,x+toolbox.gridsize,y+toolbox.gridsize-1,gridlow,1); /* bottom */ drawline(screen, x, y+toolbox.gridsize,x+toolbox.gridsize,y+toolbox.gridsize,gridlow,1); /* bottom */ drawline(screen, x, y,x,y+toolbox.gridsize,gridhigh,1); /* left */ drawline(screen, x+1, y,x+1,y+toolbox.gridsize-1,gridhigh,1); /* left */ drawline(screen, x+toolbox.gridsize, y+1,x+toolbox.gridsize,y+toolbox.gridsize,gridlow,1); /* right */ drawline(screen, x+toolbox.gridsize-1, y+1,x+toolbox.gridsize-1,y+toolbox.gridsize,gridlow,1); /* right */ for (z = y+2; z < y+toolbox.gridsize;z++) { drawline(screen,x+2,z,x+toolbox.gridsize-2,z,gridmiddle,1); } 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) { if (objfillcol.unused & USECOLOUR) { floodfill(screen, area.x + 5, area.y + 5, objfillcol); } else { floodfill(screen, area.x + 5, area.y + 5, black); drawline(screen, area.x+(area.w/2)-3, area.y+(area.h/2)-3-4, area.x+(area.w/2)+3, area.y+(area.h/2)+3-4,white,1); drawline(screen, area.x+(area.w/2)+3, area.y+(area.h/2)-3-4, area.x+(area.w/2)-3, area.y+(area.h/2)+3-4,white,1); } } if (i == TB_GRID) { if (grid) { drawbox(screen, area.x+5,area.y+20,area.x + area.w - 15, area.y + area.h - 5, black, &black); if (state == S_DRAWFLOW) { drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, yellow, &yellow); } else { drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, green, &green); } } else { drawbox(screen, area.x+5,area.y+20,area.x + area.w - 15, area.y + area.h - 5, red, &red); drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, black, &black); } } if (i == TB_LINESTYLE) { int style; /* show line thickness */ style = defthickness; drawline(screen, area.x + 5,area.y+5-(defthickness/2),area.x + area.w - 5-defthickness, area.y+5-(defthickness/2) ,white,style); /* show line style (dotted, dashed, etc)*/ style = (defstyle << 8) | 1; //drawline(screen, area.x + 5,area.y+15,area.x + area.w - 5-defthickness, area.y+15 ,white,style); drawline(screen, area.x + 5,area.y+15,area.x + area.w - 5, area.y+15 ,white,style); /* show arrow style (start, end, none) */ style = (defarrow << 16) | 1; drawline(screen, area.x + 5,area.y+24,area.x + area.w - 5, area.y+24 ,white,style); } if (i == TB_FLOW) { if (showflows) { drawbox(screen, area.x+5,area.y+20,area.x + area.w - 15, area.y + area.h - 5, black, &black); if (state == S_DRAWFLOW) { drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, yellow, &yellow); } else { drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, green, &green); } } else { drawbox(screen, area.x+5,area.y+20,area.x + area.w - 15, area.y + area.h - 5, red, &red); drawbox(screen, area.x+area.w - 14,area.y+20,area.x + area.w - 7, area.y + area.h - 5, black, &black); } } SDL_UpdateRect(screen, x, y, toolbox.gridsize+3,toolbox.gridsize+3); x += toolbox.gridsize+3; } /* draw selectors */ if (state == S_NONE) drawtoolboxselector(TB_POINTER, 0); if (state == S_ADDOBJ) drawtoolboxselector(TB_ADDOBJ, 0); if (state == S_CHANGEOBJECT) drawtoolboxselector(TB_ADDOBJ, 1); if (state == S_ADDTEXT) drawtoolboxselector(TB_ADDTEXT, 0); if (state == S_SAVING) drawtoolboxselector(TB_SAVE, 0); if (state == S_LOADING) drawtoolboxselector(TB_LOAD, 0); if (state == S_MATCHSIZE) drawtoolboxselector(TB_MATCHSIZE, 0); if (state == S_MATCHX) drawtoolboxselector(TB_MATCHPOS, 0); if (state == S_MATCHY) drawtoolboxselector(TB_MATCHPOS, 0); if (state == S_CREATETELE) drawtoolboxselector(TB_CREATETELE, 0); if (state == S_DRAWFLOW) drawtoolboxselector(TB_FLOW, 0); } void drawtoolboxselector(int buttonid, int altcolour) { SDL_Color outlinecol; int x,y; /* draw selector */ if (altcolour) { outlinecol = blue; } else { 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,1); /* top */ drawline(screen, x, y+1,x+toolbox.gridsize,y+1,outlinecol,1); /* top */ drawline(screen, x, y+toolbox.gridsize,x+toolbox.gridsize,y+toolbox.gridsize,outlinecol,1); /* bottom */ drawline(screen, x, y+toolbox.gridsize-1,x+toolbox.gridsize,y+toolbox.gridsize-1,outlinecol,1); /* bottom */ drawline(screen, x, y,x,y+toolbox.gridsize,outlinecol,1); /* left */ drawline(screen, x+1, y,x+1,y+toolbox.gridsize,outlinecol,1); /* left */ drawline(screen, x+toolbox.gridsize, y,x+toolbox.gridsize,y+toolbox.gridsize,outlinecol,1); /* right */ drawline(screen, x+toolbox.gridsize-1, y,x+toolbox.gridsize-1,y+toolbox.gridsize,outlinecol,1); /* 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, SDL_Color *overridebg) { float xscale,yscale; int realx1, realy1; int realx2, realy2; int realx3, realy3; int realx4, realy4; int i; SDL_Color linecol,fillcol, polycol, subobjfill; SDL_Surface *temp; SDL_Rect area; Uint32 bgcol; int left = 9999; int right = -1; int top = 9999; int bottom = -1; int insubobj = FALSE; subobjfill.r = 0; subobjfill.g = 0; subobjfill.b = 0; subobjfill.unused = 0; temp = NULL; xscale = (float)w / (float)vimg->w; yscale = (float)h / (float)vimg->h; polycol.unused = 0; 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 (overridebg == NULL) { //if (vimg->vector[i].c.unused == 255) { /* used to display current colour in foreground/background buttons */ // fillcol = objfillcol; //} else { //fillcol = vimg->vector[i].c; fillcol = vimg->vector[i].fc; //} } else { fillcol = *overridebg; } // scale the coords of this vector if (vimg->vector[i].type == VT_BEZIER) { int ax,ay; int bx,by; int cx,cy; int dx,dy; ax = (vimg->vector[i].x1 & 0xffff0000) >> 16; ay = (vimg->vector[i].y1 & 0xffff0000) >> 16; bx = (vimg->vector[i].x1 & 0x0000ffff); by = (vimg->vector[i].y1 & 0x0000ffff); cx = (vimg->vector[i].x2 & 0xffff0000) >> 16; cy = (vimg->vector[i].y2 & 0xffff0000) >> 16; dx = (vimg->vector[i].x2 & 0x0000ffff); dy = (vimg->vector[i].y2 & 0x0000ffff); realx1 = ((float)ax * xscale); realy1 = ((float)ay * yscale); realx2 = ((float)bx * xscale); realy2 = ((float)by * yscale); realx3 = ((float)cx * xscale); realy3 = ((float)cy * yscale); realx4 = ((float)dx * xscale); realy4 = ((float)dy * yscale); } else { realx1 = ((float)vimg->vector[i].x1 * xscale); realy1 = ((float)vimg->vector[i].y1 * yscale); realx2 = ((float)vimg->vector[i].x2 * xscale); realy2 = ((float)vimg->vector[i].y2 * yscale); realx3 = 0; realy3 = 0; realx4 = 0; realy4 = 0; } /* create temp surface */ if ((vimg->vector[i].type == VT_POLY) || (vimg->vector[i].type == VT_SUBOBJ)) { if (temp == NULL) { temp = SDL_CreateRGBSurface(SDL_SWSURFACE,w+3, h+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); // clear temp surface to bg colour bgcol = SDL_MapRGB(temp->format, 40, 50, 60); SDL_FillRect(temp, NULL, bgcol); SDL_SetColorKey(temp, SDL_SRCCOLORKEY|SDL_RLEACCEL, bgcol); // initialise border colour polycol = linecol; left = 9999; right = -1; top = 9999; bottom = -1; } } else if (vimg->vector[i].type != VT_ENDPOLY) { if (!insubobj) { temp = SDL_CreateRGBSurface(SDL_SWSURFACE,w+3, h+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); // clear temp surface to bg colour bgcol = SDL_MapRGB(temp->format, 40, 50, 60); SDL_FillRect(temp, NULL, bgcol); SDL_SetColorKey(temp, SDL_SRCCOLORKEY|SDL_RLEACCEL, bgcol); } } /* draw this vector onto a temp surface */ switch (vimg->vector[i].type) { case VT_LINE: drawline(temp,realx1,realy1, realx2,realy2,linecol,1); if (realx1 < left) left = realx1; if (realx2 < left) left = realx2; if (realx1 > right) right = realx1; if (realx2 > right) right = realx2; if (realy1 < top) top = realy1; if (realy2 < top) top = realy2; if (realy1 > bottom) bottom = realy1; if (realy2 > bottom) bottom = realy2; break; case VT_POLY: drawline(temp,realx1,realy1, realx2,realy2,polycol,1); if (realx1 < left) left = realx1; if (realx2 < left) left = realx2; if (realx1 > right) right = realx1; if (realx2 > right) right = realx2; if (realy1 < top) top = realy1; if (realy2 < top) top = realy2; if (realy1 > bottom) bottom = realy1; if (realy2 > bottom) bottom = realy2; break; case VT_SUBOBJ: insubobj = TRUE; subobjfill.r = fillcol.r; subobjfill.g = fillcol.g; subobjfill.b = fillcol.b; subobjfill.unused |= USECOLOUR; break; case VT_ENDPOLY: insubobj = FALSE; if (subobjfill.unused & USECOLOUR) { fillcol = subobjfill; subobjfill.r = 0; subobjfill.g = 0; subobjfill.b = 0; subobjfill.unused = 0; } floodfill(temp,(left+right)/2,(top+bottom)/2, fillcol); //drawline(temp,(left+right)/2,(top+bottom)/2, (left+right)/2 + 1, (top+bottom)/2 + 1, fillcol, 1); break; case VT_BOX: drawbox(temp,realx1,realy1, realx2,realy2,linecol, &fillcol); if (realx1 < left) left = realx1; if (realx2 < left) left = realx2; if (realx1 > right) right = realx1; if (realx2 > right) right = realx2; if (realy1 < top) top = realy1; if (realy2 < top) top = realy2; if (realy1 > bottom) bottom = realy1; if (realy2 > bottom) bottom = realy2; break; case VT_ELLIPSE: drawellipse(temp,realx1,realy1, realx2,realy2, linecol); if (realx1 - realx2 < left) left = realx1 - realx2; if (realx1 + realx2 > right) right = realx1 + realx2; if (realy1 - realy2 < top) top = realy1 - realy2; if (realy1 + realy2 > bottom) bottom = realy1 + realy2; break; case VT_BEZIER: drawbezier(temp,realx1,realy1, realx2,realy2, realx3,realy3, realx4,realy4, linecol); if (realx1 < left) left = realx1; if (realx2 < left) left = realx2; if (realx3 < left) left = realx3; if (realx4 < left) left = realx4; if (realx1 > right) right = realx1; if (realx2 > right) right = realx2; if (realx3 > right) right = realx3; if (realx3 > right) right = realx4; if (realy1 < top) top = realy1; if (realy2 < top) top = realy2; if (realy3 < top) top = realy3; if (realy4 < top) top = realy4; if (realy1 > bottom) bottom = realy1; if (realy2 > bottom) bottom = realy2; if (realy3 > bottom) bottom = realy3; if (realy4 > bottom) bottom = realy4; break; /*case VT_FILL: floodfill(dest,realx1,realy1, fillcol); break; */ } if (vimg->vector[i].type != VT_POLY) { if (!insubobj) { // blit surface onto drawing surface area.x = x; area.y = y; area.w = w; area.h = h; SDL_BlitSurface(temp, NULL, dest, &area); } } /* free it */ if (vimg->vector[i].type != VT_POLY) { if (!insubobj) { SDL_FreeSurface(temp); temp = NULL; } } } if (temp != NULL) { SDL_FreeSurface(temp); temp = NULL; } return; } void drawvectorSVG(vectorimg_t *vimg, int x, int y, int w, int h, SDL_Color *overridefg, SDL_Color *overridebg) { float xscale,yscale; int realx1, realy1; int realx2, realy2; int realx3, realy3; int realx4, realy4; int i; SDL_Color linecol,fillcol, polycol, subobjfill; char temp[BUFLEN]; int left = 9999; int right = -1; int top = 9999; int bottom = -1; int insubobj = FALSE; int inpoly = FALSE; int inbez = FALSE; subobjfill.r = 0; subobjfill.g = 0; subobjfill.b = 0; subobjfill.unused = 0; xscale = (float)w / (float)vimg->w; yscale = (float)h / (float)vimg->h; polycol.unused = 0; 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 (overridebg == NULL) { //if (vimg->vector[i].c.unused == 255) { /* used to display current colour in foreground/background buttons */ // fillcol = objfillcol; //} else { //fillcol = vimg->vector[i].c; fillcol = vimg->vector[i].fc; //} } else { fillcol = *overridebg; } // scale the coords of this vector if (vimg->vector[i].type == VT_BEZIER) { int ax,ay; int bx,by; int cx,cy; int dx,dy; ax = (vimg->vector[i].x1 & 0xffff0000) >> 16; ay = (vimg->vector[i].y1 & 0xffff0000) >> 16; bx = (vimg->vector[i].x1 & 0x0000ffff); by = (vimg->vector[i].y1 & 0x0000ffff); cx = (vimg->vector[i].x2 & 0xffff0000) >> 16; cy = (vimg->vector[i].y2 & 0xffff0000) >> 16; dx = (vimg->vector[i].x2 & 0x0000ffff); dy = (vimg->vector[i].y2 & 0x0000ffff); realx1 = x+ ((float)ax * xscale); realy1 = y+ ((float)ay * yscale); realx2 = x+ ((float)bx * xscale); realy2 = y+ ((float)by * yscale); realx3 = x+ ((float)cx * xscale); realy3 = y+ ((float)cy * yscale); realx4 = x+ ((float)dx * xscale); realy4 = y+ ((float)dy * yscale); } else { 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); realx3 = 0; realy3 = 0; realx4 = 0; realy4 = 0; } /* create temp surface */ if (vimg->vector[i].type == VT_POLY) { /* start of polygon */ if (inpoly == FALSE) { inpoly = TRUE; polycol = linecol; sprintf(svgbuf,"vector[i].type) { case VT_LINE: /* TODO: add style */ sprintf(svgbuf,"\n", realx1, realy1, realx2, realy2,linecol.r,linecol.g,linecol.b, 1 ); fprintf(svgfile, svgbuf); break; case VT_POLY: sprintf(temp, "L%d %d ", realx2,realy2); strcat(svgbuf, temp); if (realx1 < left) left = realx1; if (realx2 < left) left = realx2; if (realx1 > right) right = realx1; if (realx2 > right) right = realx2; if (realy1 < top) top = realy1; if (realy2 < top) top = realy2; if (realy1 > bottom) bottom = realy1; if (realy2 > bottom) bottom = realy2; break; case VT_SUBOBJ: insubobj = TRUE; subobjfill.r = fillcol.r; subobjfill.g = fillcol.g; subobjfill.b = fillcol.b; subobjfill.unused |= USECOLOUR; break; case VT_ENDPOLY: if (subobjfill.unused & USECOLOUR) { fillcol = subobjfill; subobjfill.r = 0; subobjfill.g = 0; subobjfill.b = 0; subobjfill.unused = 0; } if (inpoly) { sprintf(temp, "\" style=\"fill:rgb(%d,%d,%d);stroke:rgb(%d,%d,%d);stroke-width:1\"/>\n", fillcol.r, fillcol.g, fillcol.b, polycol.r, polycol.g, polycol.b); strcat(svgbuf, temp); fprintf(svgfile, svgbuf); } else if (inbez) { sprintf(temp, "\" style=\"fill:rgb(%d,%d,%d);stroke:rgb(%d,%d,%d);stroke-width:1\"/>\n", fillcol.r, fillcol.g, fillcol.b, polycol.r, polycol.g, polycol.b); fprintf(svgfile, temp); /*} else if (insubobj) { sprintf(svgbuf, "\" style=\"fill:rgb(%d,%d,%d);stroke:rgb(%d,%d,%d);stroke-width:1\"/>\n", fillcol.r, fillcol.g, fillcol.b, polycol.r, polycol.g, polycol.b); fprintf(svgfile, svgbuf); */ } //sprintf(svgbuf, "\n", gnum, inbez = FALSE; insubobj = FALSE; inpoly = FALSE; break; case VT_BOX: if (fillcol.unused & USECOLOUR) { sprintf(svgbuf,"\n", realx1, realy1, realx2-realx1, realy2-realy1,fillcol.r,fillcol.g,fillcol.b, linecol.r,linecol.g,linecol.b ); } else { sprintf(svgbuf,"\n", realx1, realy1, realx2-realx1, realy2-realy1,linecol.r,linecol.g,linecol.b ); } fprintf(svgfile, svgbuf); break; case VT_ELLIPSE: if (insubobj) { /* use colour from subobj */ sprintf(svgbuf,"\n", realx1, realy1, realx2-x, realy2 -y,subobjfill.r, subobjfill.g, subobjfill.b, linecol.r,linecol.g,linecol.b); } else { sprintf(svgbuf,"\n", realx1, realy1, realx2-x, realy2-y,linecol.r,linecol.g,linecol.b); } fprintf(svgfile, svgbuf); break; case VT_BEZIER: /*TODO: implement */ if (insubobj) { if (inbez) { /* sprintf(svgbuf,"T%d %d %d %d %d %d %d %d ", realx1, realy1, realx2, realy2, realx3, realy3, realx4, realy4 ); */ sprintf(svgbuf," C%d %d %d %d %d %d", realx2, realy2, realx3, realy3, realx4, realy4 ); fprintf(svgfile, svgbuf); } else { /* sprintf(svgbuf,"vector[i].type == VT_BEZIER) { if (insubobj) { /* use colour from subobj */ sprintf(svgbuf,"\" style=\"fill:rgb(%d,%d,%d);stroke-width:1;stroke:rgb(%d,%d,%d)\"/>\n", subobjfill.r, subobjfill.g, subobjfill.b, linecol.r,linecol.g,linecol.b); } else { sprintf(svgbuf,"\" style=\"stroke-width:1;stroke:rgb(%d,%d,%d)\"/>\n", linecol.r,linecol.g,linecol.b); } } return; } int endtext(void) { SDL_Rect area; int tw,th; /* 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); bg = NULL; } if (strlen(text) == 0) { sprintf(statustext,"Text entry aborted."); changestate(S_NONE); drawmap(TRUE); 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; } /* adjust for grid */ if (grid) { int m; m = map[curmap].textob[map[curmap].numtext].x; map[curmap].textob[map[curmap].numtext].x -= (m % gridsize); m = map[curmap].textob[map[curmap].numtext].y; map[curmap].textob[map[curmap].numtext].y -= (m % gridsize); } /* calculate width */ TTF_SizeText(font[DEFTEXTH], text, &tw,&th); map[curmap].textob[map[curmap].numtext].w = tw; map[curmap].textob[map[curmap].numtext].h = DEFTEXTH; map[curmap].textob[map[curmap].numtext].c = fgcol; map[curmap].textob[map[curmap].numtext].c.unused |= ~(ISFLOW); /* add to 'thing' list */ map[curmap].thing[map[curmap].numthings].type = T_TEXT; map[curmap].thing[map[curmap].numthings].id = map[curmap].numtext; setmod(TRUE); sprintf(statustext,"Added text object #%d: '%s'.",map[curmap].numtext, map[curmap].textob[map[curmap].numtext].text); drawstatusbar(); map[curmap].numtext++; map[curmap].numthings++; changestate(S_NONE); drawmap(TRUE); return FALSE; } int endtextedit(void) { SDL_Rect area; int tw,th; int si; /* 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); bg = NULL; } if (strlen(text) == 0) { return TRUE; } si = map[curmap].selecteditem; /* update text */ strcpy(map[curmap].textob[si].text, text); /* anchor, x, y, height don't change */ //map[curmap].textob[si].anchor = textanchor; //map[curmap].textob[si].x = startx; //map[curmap].textob[si].y = starty; /* calculate & update width */ TTF_SizeText(font[map[curmap].textob[si].h], text, &tw,&th); map[curmap].textob[si].w = tw; setmod(TRUE); sprintf(statustext,"Updated text object #%d to '%s'\n",si, map[curmap].textob[si].text); drawstatusbar(); changestate(S_NONE); drawmap(TRUE); return FALSE; } int endtextmove(int x, int y) { int txoff,tyoff; SDL_FreeSurface(shadow); shadow = NULL; SDL_FreeSurface(bg); bg = NULL; 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; } /* adjust for grid */ if (grid) { int m; m = map[curmap].textob[map[curmap].curtext].x + x - startx; x = x - (m % gridsize); m = map[curmap].textob[map[curmap].curtext].y + y - starty; y = y - (m % gridsize); } map[curmap].textob[map[curmap].curtext].x += (x - startx); map[curmap].textob[map[curmap].curtext].y += (y - starty); setmod(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 getmousepos (int x,int y) { if (isontoolbox(x, y)) { return MP_TOOLBOX; } else if (isonmapbox(x,y)) { if (isonmapname(x,y)) { return MP_MAPBOXNAME; } else { return MP_MAPBOXCHILDREN; } } else if (isonobox(x,y)) { return MP_OBJECTBOX; } return MP_NONE; } 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; int promptsize = 40; int yesnosize = 99; int tw,th; /* clear map to red */ area.x = 0; area.y = 0; area.w = screen->w - 1; area.h = screen->h - 1; SDL_FillRect(screen, &area, SDL_MapRGB(screen->format, 255, 0, 0)); drawbox(screen, 0, 200,(screen->w/2)-1,500,blue, NULL); drawbox(screen, screen->w/2, 200,screen->w-1,500,blue, NULL); drawtextat(screen, -1,100,prompt, promptsize, blue); /* draw yes & no */ TTF_SizeText(font[promptsize], "Yes", &tw,&th); drawtextat(screen, ((screen->w-SIDEBARW) / 4) - (tw / 2),300,"Yes", yesnosize, blue); TTF_SizeText(font[promptsize], "No", &tw,&th); drawtextat(screen, (((screen->w-SIDEBARW) / 4)*3) - (tw / 2),300,"No", yesnosize, blue); SDL_Flip(screen); } int getyn(int x, int y) { if (x >= ((screen->w - SIDEBARW)/2)) { return NO; } else { return YES; } return MAYBE; } void goback(void) { if (numhistory >= 1) { changemap(history[numhistory-1]); numhistory--; sprintf(statustext, "Drilled back to #%d (%s) - current depth is %d.",curmap,map[curmap].name, numhistory); drawmap(TRUE); } else { seterror(255); 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 getlinkat(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)) { if (!isflow(i, T_LINK) || (showflows == TRUE)) { return i; } } } return -1; } int loadmap(void) { char filename[BUFLEN]; FILE *f; int namelen; int i,n; char vers[8], *p; mapobject099a_t tempmapobjects[MAXOBJECTS]; /* TODO: validate */ strcpy(filename, text); sprintf(statustext,"Loading map...\n"); drawstatusbar(); f = fopen(filename, "rb"); if (!f) { seterror(255); sprintf(statustext,"ERROR: Cannot open '%s'.\n",filename); return TRUE; } /* TODO: free() variables! */ /* TODO: read version string */ fread(&vers, 8, 1, f); /* if no version string, then this is an old version */ if (vers[0] != 'V') { strcpy(vers, "OLD"); /* go back to start of file */ fseek(f, 0, SEEK_SET); } else { /* if we found a version string, remove trailling spaces */ for (p = vers; *p != '\0' ; p++) { if (*p == ' ') { *p = '\0'; break; } } } if (!strcmp(vers, "OLD")) { /* old versions without version string */ /* 0.99a didn't have the fillcol field in mapobject_t */ /* 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); /* read into temp area, then copy to real structure */ fread(&tempmapobjects, sizeof(mapobject099a_t), map[i].numobjects, f); for (n = 0; n < map[i].numobjects; n++) { map[i].obj[n].type = tempmapobjects[n].type; map[i].obj[n].x = tempmapobjects[n].x; map[i].obj[n].y = tempmapobjects[n].y; map[i].obj[n].w = tempmapobjects[n].w; map[i].obj[n].h = tempmapobjects[n].h; map[i].obj[n].child = tempmapobjects[n].child; map[i].obj[n].fillcol = black; map[i].obj[n].fillcol.unused &= ~(USECOLOUR); } fread(&map[i].textob, sizeof(text_t), map[i].numtext, f); } } else { /* 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); /* do some fixes for common issues (whether due to old map versions or not) */ for (i = 0; i < nummaps; i++) { for (n = 0; n < map[i].numlinks; n++) { /* old maps have line thickness = 0, change this to 1 */ if (map[i].olink[n].style == 0) { map[i].olink[n].style = 1; } /* old maps have fillcol.unused = 99 for NOCOLOUR and 100 for USECOLOUR */ /* new maps have fillcol.unused&0x01 == 1 for USECOLOUR, == 0 for NOCOLOUR */ if (map[i].olink[n].col.unused == 99) { map[i].olink[n].col.unused = 0; } if (map[i].olink[n].col.unused == 100) { map[i].olink[n].col.unused = 1; } } for (n = 0; n < map[i].numobjects; n++) { /* old maps have fillcol.unused = 99 for NOCOLOUR and 100 for USECOLOUR */ /* new maps have fillcol.unused&0x01 == 1 for USECOLOUR, == 0 for NOCOLOUR */ if (map[i].obj[n].fillcol.unused == 99) { map[i].obj[n].fillcol.unused = 0; } if (map[i].obj[n].fillcol.unused == 100) { map[i].obj[n].fillcol.unused = 1; } } for (n = 0; n < map[i].numtext; n++) { /* old maps have fillcol.unused = 99 for NOCOLOUR and 100 for USECOLOUR */ /* new maps have fillcol.unused&0x01 == 1 for USECOLOUR, == 0 for NOCOLOUR */ if (map[i].textob[n].c.unused == 99) { map[i].textob[n].c.unused = 0; } if (map[i].textob[n].c.unused == 100) { map[i].textob[n].c.unused = 1; } } } curmap = 0; grid = FALSE; setmod(FALSE); if (!autoload) { setinfo(255); } sprintf(statustext,"Successfully loaded map from '%s' (%d maps). [file version: '%s']\n",filename,nummaps, vers); strcpy(currentfilename, filename); updatewm(); drawmap(TRUE); return FALSE; } void lowerselected(int amt) { int i,n; int temptype,tempid; int target = 0; for (n = 0; n < amt; n++) { /* 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) { target = i; 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; } } if (i == 0) break; } setmod(TRUE); sprintf(statustext, "Selected item position lowered by %d (now %d of %d).", n, target+1, map[curmap].numthings); /* redraw map */ drawmap(TRUE); } 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)) ) { if (!isflow(i, T_OBJECT) || (showflows == TRUE)) { return i; } } } */ /* traverse thing list backwards so we hit "higher" objects first */ for (i = (map[curmap].numthings-1); i >= 0; i--) { if (map[curmap].thing[i].type == T_OBJECT) { int oid = map[curmap].thing[i].id; if ( (x >= map[curmap].obj[oid].x ) && (x <= (map[curmap].obj[oid].x + map[curmap].obj[oid].w)) && (y >= map[curmap].obj[oid].y ) && (y <= (map[curmap].obj[oid].y + map[curmap].obj[oid].h)) ) { if (!isflow(oid, T_OBJECT) || (showflows == TRUE)) { return oid; } } } } return -1; } void paste(void) { if (copytype == T_MAP) { if (copymap == curmap) { seterror(255); sprintf(statustext,"ERROR: copy source and destination maps are the same!"); drawstatusbar(); } else if (copymap < 0) { seterror(255); sprintf(statustext,"ERROR: No copy source selected!"); drawstatusbar(); } else { map[curmap] = map[copymap]; sprintf(map[curmap].name, "Copy of map%d",copymap); setmod(TRUE); sprintf(statustext,"Map %d ('%s') copied to map %d.", copymap, map[copymap].name, curmap); copytype = -1; copymap = -1; drawmap(TRUE); } } else if (copytype == T_TEXT) { int tnum; /* create new text object */ if ((map[copymap].textob[copyfrom].x + 10) >= map[curmap].width) { startx = map[copymap].textob[copyfrom].x - 10; } else { startx = map[copymap].textob[copyfrom].x + 10; } if ((map[copymap].textob[copyfrom].y + 10) >= map[curmap].height) { starty = map[copymap].textob[copyfrom].y - 10; } else { starty = map[copymap].textob[copyfrom].y + 10; } if (copymap == curmap) { textanchor = map[copymap].textob[copyfrom].anchor; if (textanchor != -1) { startx += map[copymap].obj[textanchor].x; starty += map[copymap].obj[textanchor].y; } } else { textanchor = -1; } strcpy(text, map[copymap].textob[copyfrom].text); /* create it */ endtext(); sprintf(statustext,"Text object pasted at %d,%d.",startx,starty); /* update its size */ tnum = map[curmap].numtext-1; map[curmap].textob[tnum].h = map[copymap].textob[copyfrom].h; map[curmap].textob[tnum].w = map[copymap].textob[copyfrom].w; map[curmap].textob[tnum].c = map[copymap].textob[copyfrom].c; /* select new item */ map[curmap].selecteditemtype = T_TEXT; map[curmap].selecteditem = tnum; /* clear buffer */ copytype = -1; copymap = -1; drawmap(TRUE); } else if (copytype == T_OBJECT) { int newtype, newx, newy, n; int newnum; newtype = map[copymap].obj[copyfrom].type; newx = map[copymap].obj[copyfrom].x + 10; newy = map[copymap].obj[copyfrom].y + 10; /* TODO: validate new position */ createobject(newtype, newx,newy); /* match size, colour, etc */ newnum = map[curmap].numobjects-1; map[curmap].obj[newnum].w = map[copymap].obj[copyfrom].w; map[curmap].obj[newnum].h = map[copymap].obj[copyfrom].h; map[curmap].obj[newnum].fillcol = map[copymap].obj[copyfrom].fillcol; /* copy over all attached text */ for (n = 0; n < map[copymap].numtext; n++) { if (map[copymap].textob[n].anchor == copyfrom) { int tnum; /* duplicate it */ startx = map[copymap].textob[n].x + map[curmap].obj[newnum].x; starty = map[copymap].textob[n].y + map[curmap].obj[newnum].y; textanchor = newnum; strcpy(text, map[copymap].textob[n].text); endtext(); /* update text size */ tnum = map[curmap].numtext-1; map[curmap].textob[tnum].h = map[copymap].textob[n].h; map[curmap].textob[tnum].w = map[copymap].textob[n].w; map[curmap].textob[tnum].c = map[copymap].textob[n].c; } } /* select new object */ map[curmap].selecteditemtype = T_OBJECT; map[curmap].selecteditem = newnum; sprintf(statustext,"Object pasted at %d,%d.",newx,newy); drawmap(TRUE); } else { seterror(255); sprintf(statustext,"Error: No copy source selected!"); drawstatusbar(); } } 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); //SDL_Flip(screen); } 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 file[BUFLEN]; Uint32 fillcol; SDL_Rect area; int x1,x2,y1,y2; SDL_Color c; SDL_Color fc; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) { printf("SDL_Init: %s\n", SDL_GetError()); exit(1); } /* open window */ //screen = SDL_SetVideoMode(DEFSCREENW, DEFSCREENH, 16, (SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE)); screen = SDL_SetVideoMode(DEFSCREENW, DEFSCREENH, 16, (SDL_SWSURFACE|SDL_RESIZABLE)); 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_SWSURFACE) { printf("HWSurface set ok.\n"); fflush(STDOUT); } if (screen->flags & SDL_DOUBLEBUF) { printf("Doublebuf set ok.\n"); fflush(STDOUT); } initvars(); /* set up icon */ sprintf(file, "icon.bmp"); icon = SDL_LoadBMP(file); if (!icon) { sprintf(file, "/usr/local/share/netmapr/icon.bmp"); icon = SDL_LoadBMP(file); } if (!icon) { sprintf(file, "%s/icon.bmp",progdir); icon = SDL_LoadBMP(file); } if (!icon) { printf("Error opening icon.bmp: %s\n", TTF_GetError()); exit(1); } SDL_WM_SetIcon(icon, NULL); updatewm(); /* load fonts */ TTF_Init(); sprintf(file, "/usr/local/share/netmapr/verdana.ttf"); for (i = 1; i < MAXLETTERHEIGHT; i++) { font[i] = TTF_OpenFont(file,i); if (!font[i]) { sprintf(file, "/usr/local/share/netmapr/verdana.ttf"); font[i] = TTF_OpenFont(file,i); } if (!font[i]) { sprintf(file, "%s/verdana.ttf",progdir); font[i] = TTF_OpenFont(file,i); } if (!font[i]) { printf("Error opening font: %s\n", TTF_GetError()); exit(1); } } //printf("Font load complete - %d sizes read.\n",MAXLETTERHEIGHT); /* initialise line styles */ linemask[LS_SOLID][0] = 1; linemask[LS_SOLID][1] = -1; linemask[LS_DOTTED][0] = 1; linemask[LS_DOTTED][1] = 0; linemask[LS_DOTTED][2] = 1; linemask[LS_DOTTED][3] = 0; linemask[LS_DOTTED][4] = -1; linemask[LS_BIGDASH][0] = 1; linemask[LS_BIGDASH][1] = 1; linemask[LS_BIGDASH][2] = 1; linemask[LS_BIGDASH][3] = 0; linemask[LS_BIGDASH][4] = 0; linemask[LS_BIGDASH][5] = 0; linemask[LS_BIGDASH][6] = -1; linemask[LS_DASHDOT][0] = 1; linemask[LS_DASHDOT][1] = 1; linemask[LS_DASHDOT][2] = 0; linemask[LS_DASHDOT][3] = 0; linemask[LS_DASHDOT][4] = 0; linemask[LS_DASHDOT][5] = 1; linemask[LS_DASHDOT][6] = 0; linemask[LS_DASHDOT][7] = 0; linemask[LS_DASHDOT][8] = 0; linemask[LS_DASHDOT][9] = -1; /* 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); updatewm(); /* set up toolbox highlight image */ toolhilite = SDL_CreateRGBSurface(SDL_SWSURFACE,toolbox.gridsize+3, toolbox.gridsize+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); fillcol = SDL_MapRGB(screen->format, 250, 250, 250); area.x = 0; area.y = 0; area.w = toolbox.gridsize+1; area.h = toolbox.gridsize+1; SDL_FillRect(toolhilite, &area, fillcol); SDL_SetAlpha(toolhilite, SDL_SRCALPHA, 128); /* initialise buffer */ buffer = SDL_CreateRGBSurface(SDL_SWSURFACE,screen->w - SIDEBARW,screen->h - STATUSH, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); if (!buffer) { printf("Cannot create buffer!\n"); exit(1); } 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, NULL)) { 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); } fc.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } fc.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } fc.b = atoi(p); fc.unused = 0; c.r = 0; c.g = 0; c.b = 0; c.unused = 0; if (addvector(&objtype[numobjtypes].vimg,VT_FILL,x1,y1,0,0,&c, &fc)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } */ } else if (!strcmp(p, "subobj")) { // get r g b fill colour p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-R on line #%d of objects file.\n",line); exit(1); } if (*p == 'n') { fc.r = 0; fc.g = 0; fc.b = 0; fc.unused = 0; } else { fc.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-G on line #%d of objects file.\n",line); exit(1); } fc.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-B on line #%d of objects file.\n",line); exit(1); } fc.b = atoi(p); fc.unused = 0 | USECOLOUR; } if (addvector(&objtype[numobjtypes].vimg,VT_SUBOBJ,0,0,0,0,&fc,&fc)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } } else if (!strcmp(p, "endsub")) { fc.r = 0; fc.g = 0; fc.b = 0; fc.unused = 0; if (addvector(&objtype[numobjtypes].vimg,VT_ENDPOLY,0,0,0,0,&fc,&fc)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } } else if (!strcmp(p, "poly")) { int count = 1; p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-R on line #%d of objects file.\n",line); exit(1); } c.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-G on line #%d of objects file.\n",line); exit(1); } c.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing line-B on line #%d of objects file.\n",line); exit(1); } c.b = atoi(p); p = strtok(NULL, " "); if (*p != 'p') { printf("Invalid syntax on line #%d of objects file - missing 'f'.\n", line); exit(1); } /* get first point */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing x1 on line #%d of objects file (polyline #%d).\n",line,count); exit(1); } x1 = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing y1 on line #%d of objects file (polyline #%d).\n",line,count); exit(1); } y1 = atoi(p); p = strtok(NULL, " "); while (*p != 'f') { /* get next set of coords */ if (*p == ',') { p = strtok(NULL, " "); } if (p == NULL) { printf("Missing x2 on line #%d of objects file (polyline #%d).\n",line,count); exit(1); } x2 = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing y2 on line #%d of objects file (polyline #%d).\n",line,count); exit(1); } y2 = atoi(p); /* write to struct */ if (addvector(&objtype[numobjtypes].vimg,VT_POLY,x1,y1,x2,y2,&c, NULL)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } x1 = x2; y1 = y2; count++; p = strtok(NULL, " "); } /* get fill details */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing FILLCOL on line #%d of objects file.\n",line); exit(1); } if (*p == 'n') { fc.r = 0; fc.g = 0; fc.b = 0; fc.unused = 0; } else { fc.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing fillcol-G on line #%d of objects file.\n",line); exit(1); } fc.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing fillcol-B on line #%d of objects file.\n",line); exit(1); } fc.b = atoi(p); fc.unused = 0; fc.unused |= USECOLOUR; } if (addvector(&objtype[numobjtypes].vimg,VT_ENDPOLY,0,0,0,0,&fc, &fc)) { 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); /* fill colour? */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } if (*p == 'n') { /* no fill */ fc.r = 0; fc.g = 0; fc.b = 0; fc.unused = 0; } else { fc.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } fc.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } fc.b = atoi(p); fc.unused = 0; fc.unused |= USECOLOUR; } if (addvector(&objtype[numobjtypes].vimg,VT_BOX,x1,y1,x2,y2,&c, &fc)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } } else if (!strcmp(p, "bezier")) { 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); } x1 = x1 << 16; x1 |= atoi(p); /* store two things in the one int */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } y1 = y1 << 16; y1 |= atoi(p); /* store two things in the one int */ 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); } x2 = x2 << 16; x2 |= atoi(p); /* store two things in the one int */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } y2 = y2 << 16; y2 |= atoi(p); /* store two things in the one int */ 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_BEZIER,x1,y1,x2,y2,&c, NULL)) { printf("Too many vectors on line %d of objects file.\n",line); exit(1); } } else if (!strcmp(p, "circle")) { 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); /* x2 is actually the x radius */ p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of objects file.\n",line); exit(1); } y2 = atoi(p); /* y2 is actually the y radius */ 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_ELLIPSE,x1,y1,x2,y2,&c, NULL)) { 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); 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, NULL)) { 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); } fc.r = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); } fc.g = atoi(p); p = strtok(NULL, " "); if (p == NULL) { printf("Missing token on line #%d of buttons file.\n",line); exit(1); } fc.b = atoi(p); fc.unused = 0; c.r = 0; c.g = 0; c.b = 0; c.unused = 0; if (addvector(&tempv,VT_FILL,x1,y1,0,0,&c, &fc)) { 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, NULL)) { 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, 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); //////////////////////////////////////////////////////////// /// 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, NULL, NULL); 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 isinhistory (int mapid) { int i; int found; found = -1; for (i = 0; i < numhistory; i++) { if (history[i] == mapid) { found = i; } } return found; } int isflow(int oid, int otype) { switch (otype) { case T_OBJECT: if (map[curmap].obj[oid].fillcol.unused & ISFLOW) return TRUE; break; case T_LINK: if (map[curmap].olink[oid].col.unused & ISFLOW) return TRUE; break; case T_TEXT: if (map[curmap].textob[oid].c.unused & ISFLOW) return TRUE; break; } return FALSE; } 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 <= (screen->w - SIDEBARW)) && (y <= (screen->h - STATUSH))) { 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+(TTF_FontHeight(font[MAPBOXTEXTHEIGHT])*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 + TTF_FontHeight(font[MAPBOXTEXTHEIGHT]))) && (x <= mapbox.x+mapbox.width) && (y <= mapbox.y+(TTF_FontHeight(font[MAPBOXTEXTHEIGHT])*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; } int isonxscrollbar(int x, int y) { if ((y >= (screen->h - STATUSH - SBSIZE)) && (y < (screen->h - STATUSH))) { if (x <= toolbox.x) { return TRUE; } } return FALSE; } int isonyscrollbar(int x, int y) { if ((x >= (screen->w - SIDEBARW - SBSIZE)) && (x < (screen->w - SIDEBARW))) { return TRUE; } return FALSE; } void initmap(int mapnum) { map[mapnum].width = DEFSCREENW - SIDEBARW; map[mapnum].height = DEFSCREENH - STATUSH; 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); } setmod(FALSE); } void initvars(void) { nummaps = 1; strcpy(typedesc[0], "None"); strcpy(typedesc[1], "Object"); strcpy(typedesc[2], "Link"); strcpy(typedesc[3], "Text"); strcpy(typedesc[4], "Linkpoint"); strcpy(typedesc[5], "Map"); strcpy(currentfilename, ""); grid = TRUE; gridsize = 15; statusbarcolour.r = 255; statusbarcolour.g = 255; statusbarcolour.b = 255; /* shortcuts */ shortcut[1] = 0; shortcut[2] = 1; shortcut[3] = 2; shortcut[4] = 3; shortcut[5] = 4; shortcut[6] = 5; shortcut[7] = 6; shortcut[8] = 12; shortcut[9] = 13; shortcut[0] = 14; initmap(0); curmap = 0; obox.x = screen->w - SIDEBARW; obox.y = ((screen->h / 4) * 3) - 10; obox.width = SIDEBARW; obox.height = screen->h - obox.y; obox.bgcol = black; obox.gridbgcol = grey; obox.gridcol = grey; obox.gridsize = 30; obox.gridrowlen = SIDEBARW / obox.gridsize; toolbox.x = screen->w - SIDEBARW; toolbox.y = 0; toolbox.width = SIDEBARW; toolbox.height = screen->h / 3; toolbox.bgcol = black; toolbox.gridsize = 30; toolbox.gridrowlen = SIDEBARW / toolbox.gridsize; mapbox.x = screen->w - SIDEBARW; mapbox.y = toolbox.y+toolbox.height+10; mapbox.width = SIDEBARW; mapbox.height = obox.y - mapbox.y - 20; mapbox.offset = 0; /* obox.x = map[curmap].width + 1; obox.y = ((map[curmap].height / 4) * 3) - 10; obox.width = SIDEBARW; obox.height = map[curmap].height - obox.y; obox.bgcol = black; obox.gridbgcol = grey; 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.gridsize = 30; toolbox.gridrowlen = SIDEBARW / toolbox.gridsize; mapbox.x = map[curmap].width + 1; mapbox.y = toolbox.y+toolbox.height+10; mapbox.width = SIDEBARW; mapbox.height = obox.y - mapbox.y - 20; mapbox.offset = 0; */ fgcol = black; objfillcol = black; objfillcol.unused &= ~(USECOLOUR); } void raiseselected(int amt) { int i,n; int temptype,tempid; int target = 0; for (n = 0; n < amt; n++) { /* 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)) { target = i; 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; } } if (i == (map[curmap].numthings-1)) break; } setmod(TRUE); sprintf(statustext, "Selected item position raised by %d (now %d of %d).", n, target+1, map[curmap].numthings); /* redraw map */ drawmap(TRUE); } void seterror (int errnum) { infoflash = 0; errorflash = errnum; olderrorticks = SDL_GetTicks(); } void setinfo (int infonum) { infoflash = infonum; errorflash = 0; oldinfoticks = SDL_GetTicks(); } void setsearchflash (int num) { searchflash = num; oldsearchticks = SDL_GetTicks(); /* copy background */ if (searchbg != NULL) { SDL_FreeSurface(searchbg); searchbg = NULL; } if (map[curmap].selecteditem != -1) { if (map[curmap].selecteditemtype == T_TEXT) { int th; SDL_Rect area; int txoff,tyoff; int anchoreditem; /* calculate text's height */ th = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); area.w = map[curmap].textob[map[curmap].selecteditem].w; area.h = th; 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; } area.x = map[curmap].textob[map[curmap].selecteditem].x - screenx + txoff; area.y = map[curmap].textob[map[curmap].selecteditem].y - screeny + tyoff; searchbg = SDL_CreateRGBSurface(SDL_SWSURFACE,area.w, area.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); SDL_BlitSurface(screen, &area, searchbg, NULL); } } } void setmod(int tf) { modified = tf; /* can't just set needtocalc to TRUE as we can't guarantee when * the screen will next be redrawn */ calcmapdimensions(); needtocalc = FALSE; updatewm(); } int savemap(void) { char filename[BUFLEN]; FILE *f; int namelen; int prevgrid; int i; int eoff; SDL_Surface *exportmap; SDL_Rect area; char vers[8]; /* 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; /* export to BMP format */ 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, screen->h - STATUSH, buffer->format->BitsPerPixel, buffer->format->Rmask, buffer->format->Gmask,buffer->format->Bmask, buffer->format->Amask); state = S_NONE; prevgrid = gridsize; setgridsize(0); drawmap(FALSE); gridsize = prevgrid; area.x = 0; area.y = 0; area.w = map[curmap].width; area.h = screen->h - STATUSH; SDL_BlitSurface(screen,&area,exportmap, 0); if (SDL_SaveBMP(exportmap, filename)) { seterror(255); sprintf(statustext,"ERROR: Could not export to BMP file '%s'.\n",filename); drawstatusbar(); return TRUE; } setinfo(255); sprintf(statustext,"Successfully exported map to Microsoft BMP file '%s'.\n",filename); drawtoolbox(); drawstatusbar(); return FALSE; } if ((filename[eoff] == '.') && ((filename[eoff+1] == 'p') || (filename[eoff+1] == 'P')) && ((filename[eoff+2] == 'n') || (filename[eoff+2] == 'N')) && ((filename[eoff+3] == 'g') || (filename[eoff+3] == 'G')) ) { exportmap = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].width, screen->h - STATUSH, buffer->format->BitsPerPixel, buffer->format->Rmask, buffer->format->Gmask,buffer->format->Bmask, buffer->format->Amask); state = S_NONE; prevgrid = gridsize; setgridsize(0); drawmap(FALSE); gridsize = prevgrid; area.x = 0; area.y = 0; area.w = map[curmap].width; area.h = screen->h - STATUSH; SDL_BlitSurface(screen,&area,exportmap, 0); if (SavePNG(filename, exportmap, TRUE)) { seterror(255); sprintf(statustext,"ERROR: Could not export to PNG file '%s'.\n",filename); drawstatusbar(); return TRUE; } setinfo(255); sprintf(statustext,"Successfully exported map to PNG file '%s'.\n",filename); drawtoolbox(); drawstatusbar(); return FALSE; } /* export to SVG format */ if ((filename[eoff] == '.') && ((filename[eoff+1] == 's') || (filename[eoff+1] == 'S')) && ((filename[eoff+2] == 'v') || (filename[eoff+2] == 'V')) && ((filename[eoff+3] == 'g') || (filename[eoff+3] == 'G')) ) { if (drawSVG(filename)) { seterror(255); sprintf(statustext,"ERROR: Could not export to SVG file '%s'.\n",filename); drawstatusbar(); return TRUE; } state = S_NONE; setinfo(255); sprintf(statustext,"Successfully exported map to Scalable Vector Graphics file '%s'.\n",filename); drawtoolbox(); drawstatusbar(); return FALSE; } } if ((f = fopen(filename, "wb")) == NULL) { seterror(255); sprintf(statustext,"ERROR: Could not open '%s'.\n",filename); drawstatusbar(); return TRUE; } /* dump version, 8 bytes, right padded with 0s */ sprintf(vers, "V%-7s", VERSION); fwrite(vers, 8, 1, f); /* 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); setmod(FALSE); setinfo(255); sprintf(statustext,"Successfully saved map to '%s'.\n",filename); /* save filename */ strcpy(currentfilename, filename); updatewm(); return 0; } void scrollmaplist(int amt) { maplistpos += amt; if (amt < 0) { if (maplistpos < 0) maplistpos = 0; } else if (amt > 0) { if (maplistpos >= nummaps) { maplistpos = nummaps - 1; } } drawmaplist(screen); } void scrollobox(int amt) { int fitx,fity,fit; if (amt < 0) { while ((obox.pos + amt) < 0 ) { amt++; } obox.pos += amt; drawobox(); } else if (amt > 0) { /* 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+amt)*3 + fit) <= (numobjtypes+2)) { while (((obox.pos+amt)*3 + fit) > (numobjtypes+2)) { amt--; } obox.pos+= amt; drawobox(); } SDL_UpdateRect(screen, obox.x, obox.y, obox.width,obox.height); } int showfiledialog(void) { Uint32 fillcol; SDL_Rect area,sarea; int y; //SDL_Color ccol; int tw,th; char t[BUFLEN]; int len; char tempbuf[BUFLEN]; int sw,sh,cwid,dummy; /* 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(t,"Enter save filename:"); break; case S_LOADING: strcpy(t,"Enter load filename:"); break; case S_MAPNAMING: strcpy(t,"Enter new map name:"); break; case S_SEARCH: strcpy(t,"Enter search string:"); break; default: strcpy(t,"Enter filename:"); break; } TTF_SizeText(font[DEFTEXTH*2], t, &tw,&th); drawtextat(buffer, -1, (map[curmap].height / 4), t, DEFTEXTH*2, black); if (state == S_SAVING) { drawtextat(buffer, -1, (map[curmap].height / 4) + (th*2), "(use extension of SVG/PNG/BMP to export)", DEFTEXTH*2, black); } /* draw outlines */ drawbox(buffer,0,0,screen->w - SIDEBARW, screen->h - STATUSH, blue, NULL); drawbox(buffer,0,((screen->h-STATUSH)/2)-2,screen->w - SIDEBARW - 1,((screen->h-STATUSH)/2)+th+2,blue, NULL); /* actually draw the text */ TTF_SizeText(font[DEFTEXTH*2], text, &tw,&th); /* 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); bg = NULL; } /* copy new background */ sarea.x = startx; sarea.y = starty; sarea.w = tw + CURSORWIDTH; // include space for cursor sarea.h = DEFTEXTH*2; if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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; // figure out where to draw cursor len = textpos - text; sprintf(tempbuf, text); tempbuf[len] = '\0'; TTF_SizeText(font[DEFTEXTH*2], tempbuf, &sw, &sh); // find width of next char if (*textpos == '\0') { cwid = CURSORWIDTH; } else { tempbuf[0] = *textpos; tempbuf[1] = '\0'; TTF_SizeText(font[DEFTEXTH*2], tempbuf, &cwid, &dummy); } /* draw cursor (a solid block) */ for (y = starty ; y < (starty + sh); y++ ) { drawline(buffer, startx + sw+1, y, startx + sw + cwid,y ,blue,1); } /* draw text */ drawtextat(buffer, startx , starty , text, DEFTEXTH*2, black); /* // draw text drawtextat(buffer, startx, starty, text, DEFTEXTH*2, black); // draw cursor (a solid block) ccol = blue; for (y = starty ; y < (starty + th); y++ ) { drawline(buffer, startx + tw, y, startx + tw + CURSORWIDTH,y,ccol,1); } */ /* blit to screen */ SDL_BlitSurface(buffer, 0, screen, 0); SDL_UpdateRect(screen, 0, 0, screen->w - SIDEBARW, screen->h - STATUSH); return FALSE; } void startedittext(int o) { SDL_Rect area; Uint32 bgcol; /* edit text */ map[curmap].selecteditem = o; map[curmap].selecteditemtype = T_TEXT; /* start listening for text input */ startx = map[curmap].textob[o].x; starty = map[curmap].textob[o].y; textanchor = map[curmap].textob[o].anchor; strcpy(text, map[curmap].textob[o].text); textpos = &text[strlen(text)]; updateheight = map[curmap].textob[o].h; bg = NULL; /* blank out where the old text was */ if (textanchor != -1) { startx += map[curmap].obj[textanchor].x; starty += map[curmap].obj[textanchor].y; } area.x = startx - screenx; area.y = starty - screeny; area.w = map[curmap].textob[o].w; area.h = TTF_FontHeight(font[map[curmap].textob[o].h]); bgcol = SDL_MapRGB(screen->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b); SDL_FillRect(screen, &area, bgcol); SDL_UpdateRect(screen, area.x,area.y,area.w,area.h); updatetextcursor(); changestate(S_EDITTEXT); } int startlink(int x, int y) { int linex1,liney1,linex2,liney2; int len; xoff = (x - screenx) + (map[curmap].obj[map[curmap].curobj].x - screenx); yoff = (y - screeny) + (map[curmap].obj[map[curmap].curobj].y - screeny); startx = x ; starty = y; if (startx < 0) printf("ERRIR!#@\n"); 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; if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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,"Moving link point #%d of link #%d... (%d,%d)\n", map[curmap].curlinkpoint,map[curmap].curlink, x, y); 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 - screenx; starty = y - screeny; changestate(S_LINKMOVING); /* copy background */ linex1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].x - screenx + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcxoff; liney1 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].srcobj].y - screeny + map[curmap].olink[map[curmap].olink[map[curmap].curlink].srcobj].srcyoff; linex2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].x - screenx + map[curmap].olink[map[curmap].olink[map[curmap].curlink].dstobj].dstxoff; liney2 = map[curmap].obj[map[curmap].olink[map[curmap].curlink].dstobj].y - screeny + 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 */ if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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; /* take a copy of the object itself */ if (shadow != NULL) { SDL_FreeSurface(shadow); shadow = NULL; } shadow = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].obj[map[curmap].curobj].w+3, map[curmap].obj[map[curmap].curobj].h+3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); drawobject(shadow, &map[curmap].obj[map[curmap].curobj], FALSE, TRUE); /* make it transparent */ SDL_SetAlpha(shadow, SDL_SRCALPHA, 128); sprintf(statustext,"Moving object #%d... (%d,%d)\n", map[curmap].curobj, x, y); drawstatusbar(); return 0; } int startresize (int x, int y) { SDL_Rect area; startx = x - screenx; starty = y - screeny; changestate(S_RESIZING); /* copy background */ if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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 - screenx; area.y = map[curmap].obj[map[curmap].curobj].y - screeny; 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; sprintf(statustext, "Resizing object #%d... (%dx%d)", map[curmap].curobj, map[curmap].obj[map[curmap].curobj].w, map[curmap].obj[map[curmap].curobj].h); drawstatusbar(); return 0; } int startresizetext(int x, int y) { SDL_Rect area; int txoff,tyoff; int tw,th; int ct; ct = map[curmap].curtext; if (map[curmap].textob[ct].anchor == -1) { txoff = 0; tyoff = 0; } else { txoff = map[curmap].obj[map[curmap].textob[ct].anchor].x; tyoff = map[curmap].obj[map[curmap].textob[ct].anchor].y; } startx = x; starty = y; changestate(S_TEXTRESIZING); /* get size */ TTF_SizeText(font[map[curmap].textob[ct].h], map[curmap].textob[ct].text, &tw, &th); sprintf(statustext, "Resizing text item #%d... (%dx%d)", ct,tw,th); drawstatusbar(); /* copy background */ if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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[ct].x + txoff; area.y = map[curmap].textob[ct].y + tyoff; area.w = map[curmap].textob[ct].x + txoff + tw; area.h = map[curmap].textob[ct].y + tyoff + th; SDL_BlitSurface(screen,&area,bg,0); bgx = area.x; bgy = area.y; bgw = area.w; bgh = area.h; return 0; } int startSVG(char *svgfilename) { if ((svgfile = fopen(svgfilename, "w+")) == NULL) { return TRUE; } fprintf(svgfile, "\n"); fprintf(svgfile, "\n\n"); fprintf(svgfile, "\n",map[curmap].width, map[curmap].height); return FALSE; } void endSVG(void) { fprintf(svgfile, "\n\n"); fclose(svgfile); } int starttextmove (int x, int y) { SDL_Rect area; int txoff,tyoff; int th; 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; th = TTF_FontHeight(font[map[curmap].textob[map[curmap].curtext].h]); startx = x ; starty = y ; changestate(S_TEXTMOVING); /* copy background */ if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } bg = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].textob[map[curmap].curtext].w,th+5, 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 = th+5; SDL_BlitSurface(screen,&area,bg,0); bgx = area.x; bgy = area.y; bgw = area.w; bgh = area.h; /* take a copy of the text itself */ if (shadow != NULL) { SDL_FreeSurface(shadow); shadow = NULL; } shadow = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].textob[map[curmap].curtext].w+3, th + 3, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); SDL_FillRect(shadow, NULL, SDL_MapRGB(shadow->format,255,255,255) ); drawtextat(shadow, 0, 0, map[curmap].textob[map[curmap].curtext].text, map[curmap].textob[map[curmap].curtext].h, map[curmap].textob[map[curmap].curtext].c ); SDL_SetColorKey(shadow, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(shadow->format,255,255,255)); SDL_SetAlpha(shadow, SDL_SRCALPHA, 128); 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)) ) { if (!isflow(i, T_TEXT) || (showflows == TRUE)) { 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)) ) { if (!isflow(i, T_TEXT) || (showflows == TRUE)) { return i; } } } } return -1; } void toggleflow(int oid, int otype) { switch (otype) { case T_OBJECT: map[curmap].obj[oid].fillcol.unused = map[curmap].obj[oid].fillcol.unused ^ ISFLOW; break; case T_LINK: map[curmap].olink[oid].col.unused = map[curmap].olink[oid].col.unused ^ ISFLOW; break; case T_TEXT: map[curmap].textob[oid].c.unused = map[curmap].textob[oid].c.unused ^ ISFLOW; break; } } void togglegrid(void) { if (grid) { grid = FALSE; setinfo(255); strcpy(statustext, "Snap-To-Grid mode disabled."); } else { grid = TRUE; setinfo(255); strcpy(statustext, "Snap-To-Grid mode enabled."); } } 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)) ) { if (!isflow(map[curmap].thing[i].id, T_OBJECT) || (showflows == TRUE)) { return i; } } break; case T_LINK: if (isonlink(map[curmap].thing[i].id, x, y)) { if (!isflow(map[curmap].thing[i].id, T_LINK) || (showflows == TRUE)) { 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)) ) { if (!isflow(map[curmap].thing[i].id, T_TEXT) || (showflows == TRUE)) { 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)) ) { if (!isflow(map[curmap].thing[i].id, T_TEXT) || (showflows == TRUE)) { return i; } } } break; } } return -1; } int updatefilename(void) { int y; SDL_Rect sarea; SDL_Rect area; SDL_Color ccol = blue; int tw,th; /* 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); bg = NULL; } /* 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; if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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 */ TTF_SizeText(font[DEFTEXTH*2], text, &tw, &th); drawtextat(screen, startx, starty, text, DEFTEXTH*2, black); /* draw cursor (a solid block) */ for (y = starty ; y < (starty + (DEFTEXTH*2)); y++ ) { drawline(screen, startx + tw, y, startx + tw + DEFTEXTW*2,y,ccol,1); } SDL_UpdateRect(screen, startx, starty, tw + 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 - screenx,liney1 - screeny,linex2,liney2, linebg); /* draw line */ drawline(screen,linex1 - screenx,liney1 - screeny,linex2,liney2, map[curmap].boxcol,1); 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); //SDL_Flip(screen); return 0; } int updatelinkpointshadow(int x, int y) { int linex1,liney1; SDL_Rect area; /* 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); /* adjust for grid */ if (grid) { x = x - (x % gridsize); y = y - (y % gridsize); } /* copy background */ linex1 = x - (LINESELHANDLESIZE / 2); liney1 = y - (LINESELHANDLESIZE / 2); if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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 */ drawbox(screen, linex1, liney1,linex1+LINESELHANDLESIZE-1,liney1+LINESELHANDLESIZE-1,black,&black); SDL_UpdateRect(screen, linex1, liney1, LINESELHANDLESIZE-1, LINESELHANDLESIZE-1); //SDL_Flip(screen); sprintf(statustext,"Moving link point #%d of link #%d... (%d,%d)\n", map[curmap].curlinkpoint,map[curmap].curlink, x, y); drawstatusbar(); 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; /* adjust for grid */ if (grid) { x = x - (x % gridsize); y = y - (y % gridsize); } /* 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 < screen->w) && (y+map[curmap].obj[map[curmap].curobj].h-1 < screen->h)) { drawbox(screen, x, y, x+map[curmap].obj[map[curmap].curobj].w-1, y+map[curmap].obj[map[curmap].curobj].h-1, map[curmap].boxcol, NULL ); SDL_BlitSurface(shadow, 0, screen, &area); } SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); sprintf(statustext,"Moving object #%d... (%d,%d)\n", map[curmap].curobj, x, y); drawstatusbar(); return 0; } int updateresizeshadow(int x, int y) { SDL_Rect sarea; SDL_Rect area; int xdiff,ydiff; xdiff = x - startx; ydiff = y - starty; /* adjust for grid */ if (grid) { int m; m = map[curmap].obj[map[curmap].curobj].x + map[curmap].obj[map[curmap].curobj].w + xdiff; xdiff -= (m % gridsize); m = map[curmap].obj[map[curmap].curobj].y + map[curmap].obj[map[curmap].curobj].h + ydiff; ydiff -= (m % gridsize); } /* 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) >= screen->w) { xdiff = 0; } if ((map[curmap].obj[map[curmap].curobj].y + map[curmap].obj[map[curmap].curobj].h + ydiff) >= screen->h) { 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 - screenx; area.y = map[curmap].obj[map[curmap].curobj].y - screeny; 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 */ drawbox(screen, map[curmap].obj[map[curmap].curobj].x - screenx, map[curmap].obj[map[curmap].curobj].y - screeny, map[curmap].obj[map[curmap].curobj].x - screenx+map[curmap].obj[map[curmap].curobj].w + xdiff, map[curmap].obj[map[curmap].curobj].y - screeny+map[curmap].obj[map[curmap].curobj].h + ydiff, map[curmap].boxcol, NULL); SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); sprintf(statustext, "Resizing object #%d... (%dx%d)", map[curmap].curobj, map[curmap].obj[map[curmap].curobj].w + xdiff, map[curmap].obj[map[curmap].curobj].h + ydiff); drawstatusbar(); return 0; } int updateresizetextshadow(int x, int y) { SDL_Rect sarea; SDL_Rect area; int xdiff,ydiff; int txoff,tyoff; int textsize; char *tp; int tw,th; int ct; int x1,y1,x2,y2; ct = map[curmap].curtext; if (map[curmap].textob[ct].anchor == -1) { txoff = 0; tyoff = 0; } else { txoff = map[curmap].obj[map[curmap].textob[ct].anchor].x; tyoff = map[curmap].obj[map[curmap].textob[ct].anchor].y; } ydiff = y - starty; /* get text height */ th = TTF_FontHeight(font[map[curmap].textob[map[curmap].curtext].h]); if ((map[curmap].textob[ct].h + ydiff) >= MAXLETTERHEIGHT) ydiff = MAXLETTERHEIGHT - map[curmap].textob[ct].h - 1; if ((map[curmap].textob[ct].h + ydiff) < MINLETTERHEIGHT) ydiff = MINLETTERHEIGHT - map[curmap].textob[ct].h; /* calculate x based on text height and length */ textsize = map[curmap].textob[map[curmap].curtext].h + ydiff; tp = map[curmap].textob[map[curmap].curtext].text; TTF_SizeText(font[textsize], tp, &tw, &th); x = startx + tw; xdiff = tw - map[curmap].textob[map[curmap].curtext].w; /* 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[ct].x + txoff - screenx; area.y = map[curmap].textob[ct].y + tyoff - screeny; area.w = tw+2; area.h = th+4; 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; SDL_BlitSurface(screen,&area,bg,0); bgx = area.x; bgy = area.y; bgw = area.w; bgh = area.h; /* draw box */ x1 = map[curmap].textob[ct].x + txoff - screenx; y1 = map[curmap].textob[ct].y + tyoff - screeny; x2 = map[curmap].textob[ct].x + txoff + tw - screenx; y2 = map[curmap].textob[ct].y + tyoff + th - screeny; drawbox(screen, x1, y1, x2, y2, map[curmap].boxcol, NULL); SDL_UpdateRect(screen, x1, y1, x2-x1+1, y2-y1+1); sprintf(statustext, "Resizing text item #%d... (%dx%d)", ct,tw,th); drawstatusbar(); return 0; } int updatetextcursor(void) { int y; SDL_Rect sarea; SDL_Rect area; SDL_Color ccol = blue; int tw,th; int len; //int lenpix; int sw,sh; int cwid, dummy; char tempbuf[BUFLEN]; if ((state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING) || (state == S_SEARCH)) { showfiledialog(); return 0; } /* paste old background */ if (bg != NULL) { /* area.x = bgx - screenx; area.y = bgy - screeny; */ 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); // free it SDL_FreeSurface(bg); bg = NULL; } /* copy new background */ sarea.x = startx - screenx; sarea.y = starty - screeny; /* calculate text width */ TTF_SizeText(font[updateheight], text, &tw, &th); sarea.w = tw + CURSORWIDTH + 3; sarea.h = th; //sarea.h = DEFTEXTH; //sarea.w = ((strlen(text)+1) * (DEFTEXTW)) +2; // include space for cursor if (bg != NULL) { SDL_FreeSurface(bg); bg = NULL; } 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; // xxxxxxxxxx // figure out where to draw cursor len = textpos - text; sprintf(tempbuf, text); tempbuf[len] = '\0'; TTF_SizeText(font[updateheight], tempbuf, &sw, &sh); // find width of next char if (*textpos == '\0') { cwid = CURSORWIDTH; } else { tempbuf[0] = *textpos; tempbuf[1] = '\0'; TTF_SizeText(font[updateheight], tempbuf, &cwid, &dummy); } /* draw cursor (a solid block) */ for (y = starty ; y < (starty + sh); y++ ) { drawline(screen, startx - screenx + sw+1, y - screeny, startx - screenx + sw + cwid,y - screeny,ccol,1); } /* draw text */ drawtextat(screen, startx - screenx, starty - screeny, text, updateheight, fgcol); // update screen SDL_UpdateRect(screen, startx - screenx, starty - screeny, tw + cwid + 3 , th); //SDL_Flip(screen); return FALSE; } int endlink(int x, int y) { int endxoff,endyoff; int i; Uint8 style, arrow, thickness; int insertpoint; /* replace old bg */ pasteline(screen,linebg); /* check if we've exceeded the max number of links */ if ((map[curmap].numlinks+1) >= MAXLINKS) { seterror(255); 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); /* adjust for grid */ if (grid) { xoff = xoff - ((map[curmap].obj[startobj].x + xoff) % gridsize); yoff = yoff - ((map[curmap].obj[startobj].y + yoff) % gridsize); endxoff = endxoff - ((map[curmap].obj[startobj].x + endxoff) % gridsize); endyoff = endyoff - ((map[curmap].obj[startobj].y + endyoff) % gridsize); } 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].col.unused &= ~(ISFLOW); map[curmap].olink[map[curmap].numlinks].npoints = 0; arrow = defarrow; style = defstyle; thickness = defthickness; map[curmap].olink[map[curmap].numlinks].style = (arrow << 16) | (style << 8) | (thickness); /* add to 'thing' list */ /* links start below their endpoints but above other things */ /* shuffle all things up */ /* find lowest of endpoint ids */ insertpoint = 9999; /* default to 0 */ for (i = 0; i < (map[curmap].numthings-1); i++) { if (map[curmap].thing[i].type == T_OBJECT) { if ((map[curmap].thing[i].id == startobj) || (map[curmap].thing[i].id == endobj)) { insertpoint = i; break; } } } if (insertpoint == 9999) { insertpoint = 0; } for (i = (map[curmap].numthings-1); i >= insertpoint ; 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[insertpoint].type = T_LINK; map[curmap].thing[insertpoint].id = map[curmap].numlinks; setmod(TRUE); sprintf(statustext,"Link #%d created (from object #%d to object #%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; setmod(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; setmod(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) { SDL_FreeSurface(bg); bg = NULL; } /* adjust for grid */ if (grid) { x = x - (x % gridsize); y = y - (y % gridsize); } map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].x = x; map[curmap].olink[map[curmap].curlink].point[map[curmap].curlinkpoint].y = y; setmod(TRUE); sprintf(statustext,"Point #%d of link #%d moved to (%d,%d).\n",map[curmap].curlinkpoint, map[curmap].curlink, 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; setmod(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; setmod(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); setmod(TRUE); /* TODO: move the line */ return 0; } void drillto(int mapnum) { if (mapnum == C_NONE) { 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 */ changemap(nummaps); nummaps++; setinfo(255); sprintf(statustext,"Drilled down (new map created)."); startx = 1; starty = ((screen->h - STATUSH)/2)-2; bg = NULL; strcpy(text, map[curmap].name); changestate(S_MAPNAMING); drawmap(TRUE); } else { seterror(255); sprintf(statustext, "ERROR: Maximum number of maps reached."); drawstatusbar(); } } else if (mapnum == C_SCROLLUP) { mapbox.offset--; drawmapbox(); } else if (mapnum == C_SCROLLDOWN) { mapbox.offset++; drawmapbox(); } else { int found; /* is map already in history? */ found = isinhistory(mapnum); if (found >= 0) { /* jump back up to that point on the "stack" */ numhistory = found; } else { /* push current map */ history[numhistory] = curmap; numhistory++; } changemap(mapnum); if (found >= 0) { sprintf(statustext,"Drilled back to map #%d (%s) - current depth is %d.",curmap,map[curmap].name, numhistory); } else { sprintf(statustext,"Drilled down into map #%d (%s) - current depth is %d.",curmap,map[curmap].name, numhistory); } drawmap(TRUE); } } int endobjmove(int x, int y) { int newx, newy; SDL_FreeSurface(bg); bg = NULL; SDL_FreeSurface(shadow); shadow = NULL; /* 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; } setmod(TRUE); newx = map[curmap].obj[map[curmap].curobj].x + (x - startx); newy = map[curmap].obj[map[curmap].curobj].y + (y - starty); /* adjust for grid */ if (grid) { newx = newx - (newx % gridsize); newy = newy - (newy % gridsize); } map[curmap].obj[map[curmap].curobj].x = newx; map[curmap].obj[map[curmap].curobj].y = newy; return 0; } int endresize(int x, int y) { int origw,origh; int neww,newh; int i; float xscale,yscale; SDL_FreeSurface(bg); bg = NULL; 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; } /* adjust for grid */ if (grid) { int m; m = map[curmap].obj[map[curmap].curobj].x + neww; neww -= (m % gridsize); m = map[curmap].obj[map[curmap].curobj].y + newh; newh -= (m % gridsize); } map[curmap].obj[map[curmap].curobj].w = neww; map[curmap].obj[map[curmap].curobj].h = newh; sprintf(statustext, "Object #%d resized to %dx%d.",map[curmap].curobj,map[curmap].obj[map[curmap].curobj].w, map[curmap].obj[map[curmap].curobj].h); /* 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; /* adjust links for grid */ /* 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; } } setmod(TRUE); drawmap(TRUE); return 0; } int endtextresize(int x, int y) { int origw,origh; int neww,newh; char *tp; int tw,th; SDL_FreeSurface(bg); bg = NULL; 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].h + (y - starty) > 0) { newh = map[curmap].textob[map[curmap].curtext].h + (y - starty); } /* check for valid height */ if (newh < MINLETTERHEIGHT) newh = MINLETTERHEIGHT; if (newh >= MAXLETTERHEIGHT) newh = MAXLETTERHEIGHT-1; if ((map[curmap].textob[map[curmap].curtext].y + newh) >= map[curmap].height ) newh = map[curmap].height - map[curmap].textob[map[curmap].curtext].y - 1; /* calculate new width based on height */ tp = map[curmap].textob[map[curmap].curtext].text; TTF_SizeText(font[newh], tp, &tw, &th); neww = tw; if ((map[curmap].textob[map[curmap].curtext].x + neww) >= map[curmap].width ) neww = map[curmap].width - map[curmap].textob[map[curmap].curtext].x - 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; */ setmod(TRUE); sprintf(statustext, "Text item #%d resized to %d points (%dx%d).",map[curmap].curtext,map[curmap].textob[map[curmap].curtext].h, tw, th); drawmap(TRUE); return 0; } int updatetextshadow(int x, int y) { int th; 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); /* adjust for grid */ if (grid) { x = x - (x % gridsize); y = y - (y % gridsize); } th = TTF_FontHeight(font[map[curmap].textob[map[curmap].curtext].h]); /* copy current bg */ area.x = x; area.y = y; area.w = map[curmap].textob[map[curmap].curtext].w; area.h = th+5; 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,1); drawline(screen,x,y,x,y+map[curmap].textob[map[curmap].curtext].h-1, map[curmap].boxcol,1); 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,1); 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,1); */ drawbox(screen, x, y, x+area.w-1, y+th+2, map[curmap].boxcol, NULL); SDL_BlitSurface(shadow, 0, screen, &area); } SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); return 0; } void updatewm(void) { char progname[SMALLBUFLEN]; char verstring[BUFLEN]; char filestring[BUFLEN]; if (readonly) { sprintf(progname, "netmapr viewer"); } else { sprintf(progname, "netmapr"); } if (!strcmp(currentfilename,"")) { strcpy(filestring, "(no file)"); } else { strcpy(filestring, currentfilename); } sprintf(verstring, "%s v%s - %s %s", progname, VERSION, filestring, modified ? "*" : ""); SDL_WM_SetCaption(verstring, progname); }