A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 #include <stdio.h> 2 #include <stdarg.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <time.h> 6 #include <sys/time.h> 7 #include <sys/types.h> 8 #include <unistd.h> 9 10 #include <math.h> 11 12 #include <SDL.h> 13 #include <SDL_ttf.h> 14 #include <SDL_keysym.h> 15 16 #include "savepng.h" 17 #include "netmapr.h" 18 #include "constants.h" 19 20 SDL_Surface *screen, *buffer; 21 SDL_Surface *emptyimg; 22 SDL_Surface *icon; 23 SDL_Event event; 24 int isevent; 25 26 char svgbuf[BUFLEN]; 27 FILE *svgfile; 28 29 TTF_Font *font[MAXLETTERHEIGHT]; 30 31 SDL_Color white = { 255, 255, 255, USECOLOUR}; 32 SDL_Color black = { 0, 0, 0, USECOLOUR}; 33 SDL_Color red = { 255, 0, 0, USECOLOUR}; 34 SDL_Color green = { 0, 255, 0, USECOLOUR}; 35 SDL_Color blue = { 0, 0, 255, USECOLOUR}; 36 SDL_Color blue2 = { 0, 0, 70, USECOLOUR}; 37 SDL_Color yellow = { 255, 255, 0, USECOLOUR}; 38 SDL_Color cyan = { 0, 255, 255, USECOLOUR}; 39 SDL_Color purple = { 255, 0, 255, USECOLOUR}; 40 SDL_Color grey = { 90, 90, 90, USECOLOUR}; 41 SDL_Color grey2 = { 70, 70, 70, USECOLOUR}; 42 SDL_Color grey3 = { 50, 50, 50, USECOLOUR}; 43 SDL_Color grey4 = { 30, 30, 30, USECOLOUR}; 44 45 SDL_Color statusbarcolour = { 255, 255, 255, 0 }; 46 47 SDL_Surface *searchbg; 48 int searchflash = 0; 49 int searchcounter = 0; 50 int searchticks = 0; 51 int oldsearchticks = 0; 52 53 int errorflash = 0; 54 int errorcounter = 0; 55 int errorticks = 0; 56 int olderrorticks = 0; 57 58 int infoflash = 0; 59 int infocounter = 0; 60 int infoticks = 0; 61 int oldinfoticks = 0; 62 63 SDL_Color gridhigh = {255, 255, 255, 0}; 64 SDL_Color gridmiddle = {90, 90, 90, 0}; 65 SDL_Color gridlow = {50, 50, 50, 0}; 66 67 SDL_Cursor *normalmouse; 68 SDL_Cursor *objmouse; 69 SDL_Cursor *textmouse; 70 71 72 int linemask[MAXLINESTYLE][LINESTYLESIZE]; 73 74 xy_t fillstack[MAXFILLSTACK]; 75 int fillstackptr = 0; 76 77 /* screen "viewpane" position */ 78 int screenx = 0; 79 int screeny = 0; 80 81 int thingdrawn[MAXOBJECTS + MAXLINKS]; 82 83 SDL_Color fgcol; 84 SDL_Color objfillcol; 85 Uint8 defthickness = 1; 86 Uint8 defstyle = LS_SOLID; 87 Uint8 defarrow = 0; 88 89 int modified = FALSE; 90 int readonly = FALSE; 91 int needtocalc = FALSE; 92 93 int maplistpos = 0; /* scroll position in map list */ 94 95 int copyfrom = -1; 96 int copymap = -1; 97 int copytype = T_MAP; 98 99 int searchmap = 0; 100 int searchtob = 0; 101 int searchwrap = FALSE; 102 char searchtext[BUFLEN]; 103 104 int grid = TRUE; 105 int gridsize = 15; 106 int gridsizelist[] = {0, 10, 15, 20}; 107 int gridsizeindex = 1; 108 int gridsizenum = 4; 109 SDL_Color gridcol = {192, 192, 192, 0 }; 110 111 int oldshowflows = FALSE; 112 int showflows = FALSE; 113 114 int shortcut[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 115 int shortcutnum = 10; 116 117 int matchtype = 0; 118 119 int numobjtypes = 0; 120 int numletters = 0; 121 int numbuttons = 0; 122 int nummaps = 1; 123 124 int history[MAXHISTORY]; 125 int numhistory = 0; 126 127 int children[MAXCHILDREN]; 128 int numchildren = 0; 129 130 131 char currentfilename[BUFLEN]; 132 int state = S_NONE; 133 SDL_Surface *shadow = NULL; /* for object moves */ 134 SDL_Surface *bg = NULL; /* background for temp images*/ 135 int *linebg; /* background for temp lines */ 136 int bgx,bgy; 137 int bgw,bgh; 138 int xoff,yoff; 139 SDL_Rect temparea; 140 char statustext[BUFLEN]; 141 char oldstatustext[BUFLEN]; 142 int rollover = FALSE; 143 int oldmousepos = -1; 144 int mousepos = 0; 145 int oldselection = -1; 146 int dontpaste = FALSE; 147 148 SDL_Surface *toolbg; 149 SDL_Surface *toolhilite; 150 151 int curmap = 0; 152 153 int startx,starty; 154 int textanchor; 155 char text[BUFLEN]; 156 int startobj,endobj; 157 int updateheight; 158 char * textpos; // new 159 160 char progdir[BUFLEN]; 161 162 int shift; 163 int autoload = FALSE; 164 165 int main (int argc, char **argv) { 166 int done; 167 int c; 168 int c2; 169 int mod = FALSE; 170 int tmod; 171 int o; 172 Uint32 oldticks = 0; 173 Uint32 ticks; 174 int doubleclick = FALSE; 175 int n,found,delmap; 176 int mx,my,mb; 177 178 if (argc >= 2) { 179 int i; 180 strcpy(text, argv[1]); 181 /* cope with spaces in filenames */ 182 for (i = 2; i < argc; i++) { 183 strcat(text, " "); 184 strcat(text, argv[i]); 185 } 186 autoload = TRUE; 187 } 188 189 if (getenv("NETMAPRDIR") != NULL) { 190 strncpy(progdir, getenv("NETMAPRDIR"), BUFLEN); 191 } else { 192 strcpy(progdir, "/usr/local/share/netmapr"); 193 } 194 195 if (strstr(argv[0], "view")) { 196 readonly = TRUE; 197 } 198 199 /* 200 if (readonly) { 201 printf("Starting netmapr viewer v%s...\n", VERSION); 202 } else { 203 printf("Starting netmapr v%s...\n", VERSION); 204 } 205 */ 206 207 208 209 if (initgraphics()) { 210 printf("Error initialising graphics.\n"); 211 exit(1); 212 } 213 atexit(cleanup); 214 215 SDL_EnableUNICODE(1); 216 217 218 if (autoload) { 219 loadmap(); 220 strcpy(text, ""); 221 textpos = text; 222 } 223 224 225 if (readonly) { 226 sprintf(statustext, "Welcome to netmapr viewer v%s. Author: rob@nethack.net", VERSION); 227 } else { 228 sprintf(statustext, "Welcome to netmapr v%s. Author: rob@nethack.net", VERSION); 229 } 230 strcpy(oldstatustext,statustext); 231 drawscreen(); 232 233 /* main loop */ 234 done = 0; 235 236 while (!done) { 237 /* fade search result indicator */ 238 if (searchflash > 0) { 239 searchticks = SDL_GetTicks(); 240 if (searchticks - oldsearchticks >= SEARCHFLASHSPEED) { 241 searchflash--; 242 /* show the found object */ 243 switch (state) { 244 case S_SAVING: 245 case S_LOADING: 246 case S_FGCOL: 247 case S_MAPNAMING: 248 case S_CREATETELE: 249 case S_REALLYQUIT: 250 case S_FILLCOL: 251 case S_SEARCH: 252 break; 253 default: 254 drawsearchflash(); 255 break; 256 } 257 258 oldsearchticks = searchticks; 259 } 260 } 261 /* fade error panel */ 262 if (errorflash > 0) { 263 errorticks = SDL_GetTicks(); 264 if (errorticks - olderrorticks >= ERRORFLASHSPEED) { 265 errorflash--; 266 drawstatusbar(); 267 268 olderrorticks = errorticks; 269 } 270 } 271 /* fade info panel */ 272 if (infoflash > 0) { 273 infoticks = SDL_GetTicks(); 274 if (infoticks - oldinfoticks >= INFOFLASHSPEED) { 275 /* don't fade this if we're in a mode where the user 276 has to do something special */ 277 switch (state) { 278 case S_MATCHX: 279 case S_MATCHY: 280 case S_MATCHSIZE: 281 case S_CREATETELE: 282 case S_CHANGEOBJECT: 283 case S_DRAWFLOW: 284 break; 285 default: 286 infoflash--; 287 break; 288 } 289 drawstatusbar(); 290 291 oldinfoticks = infoticks; 292 } 293 } 294 /* check for input */ 295 //while (SDL_PollEvent(&event)) { 296 isevent = TRUE; 297 if (infoflash || errorflash || searchflash) { 298 if (!SDL_PollEvent(&event)) isevent = FALSE; 299 } else { 300 if (!SDL_WaitEvent(&event)) isevent = FALSE; 301 } 302 303 while (isevent) { 304 switch (event.type) { 305 case SDL_VIDEORESIZE: 306 /* set screen size */ 307 screen = SDL_SetVideoMode(event.resize.w > MINSCREENX ? event.resize.w : MINSCREENX, 308 event.resize.h > MINSCREENY ? event.resize.h : MINSCREENY, 309 //map[curmap].bpp, SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); 310 map[curmap].bpp, SDL_SWSURFACE|SDL_RESIZABLE); 311 SDL_FreeSurface(buffer); 312 buffer = SDL_CreateRGBSurface(SDL_SWSURFACE,screen->w - SIDEBARW,screen->h - STATUSH, 313 screen->format->BitsPerPixel, screen->format->Rmask, 314 screen->format->Gmask,screen->format->Bmask, 315 screen->format->Amask); 316 calcmapdimensions(); 317 drawscreen(); 318 break; 319 case SDL_MOUSEBUTTONDOWN: 320 searchflash = 0; 321 if (isonxscrollbar(event.button.x, event.button.y)) { 322 /* middle of the screen goes to where we clicked */ 323 screenx = (((double)event.button.x / (double)(screen->w - SIDEBARW)) * map[curmap].width) 324 - ((screen->w - SIDEBARW)/2); 325 326 validatescreenpos(); 327 drawxscrollbar(); 328 changestate(S_XSCROLL); 329 } else if (isonyscrollbar(event.button.x, event.button.y)) { 330 /* middle of the screen goes to where we clicked */ 331 screeny = (((double)event.button.y / (double)(screen->h - STATUSH - SBSIZE)) * map[curmap].height) 332 - ((screen->h - STATUSH - SBSIZE)/2); 333 334 validatescreenpos(); 335 drawyscrollbar(); 336 changestate(S_YSCROLL); 337 } else if (isonmap(event.button.x, event.button.y)) { 338 event.button.x += screenx; 339 event.button.y += screeny; 340 if (state == S_NONE) { 341 mod = SDL_GetModState(); 342 if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_SHIFT))) { 343 /* centre map on clicked position */ 344 screenx = event.button.x - ((screen->w - SIDEBARW)/2); 345 screeny = event.button.y - ((screen->h - STATUSH)/2); 346 validatescreenpos(); 347 drawmap(TRUE); 348 } else if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_CTRL) == 0)) { 349 /* is there a selected link? if so check for it first */ 350 if ((map[curmap].selecteditemtype == T_LINK) && (map[curmap].selecteditem != -1) && 351 (isonlinkdst(map[curmap].selecteditem, event.button.x,event.button.y)) ) { 352 353 map[curmap].curlink = map[curmap].selecteditem; 354 startlinkdstmove(event.button.x, event.button.y); 355 } else if ((map[curmap].selecteditemtype == T_LINK) && (map[curmap].selecteditem != -1) && 356 (isonlinksrc(map[curmap].selecteditem, event.button.x,event.button.y)) ) { 357 map[curmap].curlink = map[curmap].selecteditem; 358 startlinksrcmove(event.button.x, event.button.y); 359 } else if ( ((map[curmap].selecteditemtype == T_LINK) || (map[curmap].selecteditemtype == T_LINKPOINT)) 360 && (map[curmap].selecteditem != -1) && 361 (isonlinkpoint(map[curmap].selecteditem, event.button.x,event.button.y) != -1) ) { 362 map[curmap].curlink = map[curmap].selecteditem; 363 map[curmap].curlinkpoint = isonlinkpoint(map[curmap].selecteditem, event.button.x,event.button.y); 364 startlinkpointmove(event.button.x, event.button.y); 365 } else { 366 // move/select object 367 o = thingat(event.button.x, event.button.y); 368 if (o != -1) { 369 switch (map[curmap].thing[o].type) { 370 case T_OBJECT: 371 map[curmap].curobj = map[curmap].thing[o].id; 372 startobjmove(event.button.x,event.button.y); 373 break; 374 case T_LINK: 375 map[curmap].curlink = map[curmap].thing[o].id; 376 startlinkmove(event.button.x, event.button.y); 377 break; 378 case T_TEXT: 379 map[curmap].curtext = map[curmap].thing[o].id; 380 starttextmove(event.button.x, event.button.y); 381 break; 382 } 383 } else { 384 /* just clear the status text */ 385 sprintf(statustext, "Ready."); 386 drawstatusbar(); 387 } 388 } 389 } else if ((event.button.button == SDL_BUTTON_MIDDLE) || 390 ((event.button.button == SDL_BUTTON_LEFT) && (mod & KMOD_CTRL))) { 391 // if we're over an object, start drawing a new link 392 o = objat(event.button.x, event.button.y); 393 if (o != -1) { 394 map[curmap].curobj = o; 395 startlink(event.button.x,event.button.y); 396 } 397 } else if (event.button.button == SDL_BUTTON_RIGHT) { 398 // resize text 399 o = textat(event.button.x, event.button.y); 400 if (o != -1) { 401 map[curmap].curtext = o; 402 startresizetext(event.button.x,event.button.y); 403 } else { 404 // resize object 405 o = objat(event.button.x, event.button.y); 406 if (o != -1) { 407 map[curmap].curobj = o; 408 startresize(event.button.x,event.button.y); 409 } 410 } 411 412 413 /* 414 // resize object 415 o = objat(event.button.x, event.button.y); 416 if (o != -1) { 417 map[curmap].curobj = o; 418 startresize(event.button.x,event.button.y); 419 } else { 420 // resize text 421 o = textat(event.button.x, event.button.y); 422 if (o != -1) { 423 map[curmap].curtext = o; 424 startresizetext(event.button.x,event.button.y); 425 } 426 } 427 */ 428 } else if (event.button.button == SDL_BUTTON_WHEELUP) { 429 int amt; 430 431 tmod = SDL_GetModState(); 432 if ((mod & KMOD_SHIFT)) { 433 amt = (map[curmap].numthings / MULTIRAISENUM); 434 } else amt = 1; 435 436 if (map[curmap].selecteditem != -1) { 437 /* raise the selected object */ 438 raiseselected(amt); 439 } 440 } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { 441 int amt; 442 443 tmod = SDL_GetModState(); 444 if ((mod & KMOD_SHIFT)) { 445 amt = (map[curmap].numthings / MULTIRAISENUM); 446 } else amt = 1; 447 448 if (map[curmap].selecteditem != -1) { 449 /* lower the selected object */ 450 lowerselected(amt); 451 } 452 } 453 } /* end if state = none */ 454 } else if (isonobox(event.button.x, event.button.y)) { 455 int amt = 1; 456 457 tmod = SDL_GetModState(); 458 if ((mod & KMOD_SHIFT)) { 459 amt = 4; 460 } 461 462 if (event.button.button == SDL_BUTTON_WHEELUP) { 463 scrollobox(-amt); 464 } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { 465 scrollobox(amt); 466 } 467 } 468 break; 469 case SDL_MOUSEBUTTONUP: 470 searchflash = 0; 471 mod = SDL_GetModState(); 472 if ((event.button.button == SDL_BUTTON_LEFT) && ((mod & KMOD_CTRL) == 0)) { 473 ticks = SDL_GetTicks(); 474 if ((ticks - oldticks) <= DOUBLECLICKTHRES) { 475 doubleclick = TRUE; 476 } else { 477 doubleclick = FALSE; 478 } 479 oldticks = ticks; 480 481 if ((state == S_XSCROLL) || (state == S_YSCROLL)) { 482 changestate(S_NONE); 483 drawmap(TRUE); 484 } else if (state == S_EDITTEXT) { 485 endtextedit(); 486 } else if (state == S_TYPETEXT) { 487 endtext(); 488 } else if (isonmap(event.button.x, event.button.y)) { 489 event.button.x += screenx; 490 event.button.y += screeny; 491 if (state != S_REALLYQUIT) { 492 //if ((doubleclick) && (objat(event.button.x, event.button.y) == map[curmap].selecteditem)) { 493 if (doubleclick) { 494 o = objat(event.button.x, event.button.y); 495 496 /* only works on an object */ 497 //if (map[curmap].selecteditem != -1) { 498 if (o != -1) { 499 /* can't create a new child via double click */ 500 if (map[curmap].obj[o].child != -1) { 501 changestate(S_NONE); 502 drillto(map[curmap].obj[o].child); 503 } else { 504 seterror(255); 505 sprintf(statustext, "Cannot drill down - object has no children (use drill tool to create one)."); 506 map[curmap].selecteditem = -1; 507 changestate(S_NONE); 508 drawmap(TRUE); 509 } 510 } else { 511 o = textat(event.button.x, event.button.y); 512 if (o != -1) { 513 startedittext(o); 514 } 515 } 516 } 517 } 518 if (state == S_NONE) { 519 if (map[curmap].selecteditem != -1) { 520 map[curmap].selecteditem = -1; 521 map[curmap].selecteditemtype = T_EMPTY; 522 sprintf(statustext,"Objects/lines deselected.\n"); 523 drawmap(TRUE); 524 } 525 } else if (state == S_DRAWFLOW) { 526 int clickedtype = -1; 527 o = textat(event.button.x, event.button.y); 528 if (o == -1) { 529 o = objat(event.button.x, event.button.y); 530 if (o == -1) { 531 o = getlinkat(event.button.x, event.button.y); 532 if (o != -1) { 533 clickedtype = T_LINK; 534 } 535 } else { 536 clickedtype = T_OBJECT; 537 } 538 } else { 539 clickedtype = T_TEXT; 540 } 541 if (clickedtype == -1) { 542 /* reset to old showflows value */ 543 changestate(S_NONE); 544 drawmap(TRUE); 545 } else { 546 toggleflow(o, clickedtype); 547 if (isflow(o, clickedtype)) { 548 setinfo(255); 549 sprintf(statustext, "%s #%d traffic flow status = TRUE.", typedesc[clickedtype], o); 550 } else { 551 setinfo(255); 552 sprintf(statustext, "%s #%d traffic flow status = FALSE.", typedesc[clickedtype], o); 553 } 554 drawmap(TRUE); 555 } 556 } else if (state == S_REALLYQUIT) { 557 o = getyn(event.button.x-screenx, event.button.y-screeny); 558 if (o == YES) { 559 done = TRUE; 560 } else { 561 changestate(S_NONE); 562 drawmap(TRUE); 563 } 564 } else if (state == S_MATCHSIZE) { 565 if (matchtype == T_OBJECT) { 566 o = objat(event.button.x, event.button.y); 567 if (o == -1) { 568 changestate(S_NONE); 569 sprintf(statustext, "Size match mode aborted."); 570 drawstatusbar(); 571 } else { 572 int n; 573 /* resize selected item to match one which was clicked */ 574 map[curmap].obj[map[curmap].selecteditem].w = map[curmap].obj[o].w; 575 map[curmap].obj[map[curmap].selecteditem].h = map[curmap].obj[o].h; 576 /* adjust offsets on all links to/from object */ 577 for (n = 0; n < map[curmap].numlinks; n++) { 578 if (map[curmap].olink[n].srcobj == map[curmap].selecteditem) { 579 map[curmap].olink[n].srcxoff = (map[curmap].obj[o].w / 2); 580 map[curmap].olink[n].srcyoff = (map[curmap].obj[o].h / 2); 581 } 582 if (map[curmap].olink[n].dstobj == map[curmap].selecteditem) { 583 map[curmap].olink[n].dstxoff = (map[curmap].obj[o].w / 2); 584 map[curmap].olink[n].dstyoff = (map[curmap].obj[o].h / 2); 585 } 586 } 587 changestate(S_NONE); 588 sprintf(statustext, "Object #%d resized to match object #%d.",map[curmap].selecteditem,o); 589 drawmap(TRUE); 590 } 591 } else if (matchtype == T_TEXT) { 592 o = textat(event.button.x, event.button.y); 593 if (o == -1) { 594 changestate(S_NONE); 595 sprintf(statustext, "Size match mode aborted."); 596 drawstatusbar(); 597 } else { 598 int tw,th; 599 /* resize selected text to match one which was clicked */ 600 map[curmap].textob[map[curmap].selecteditem].h = map[curmap].textob[o].h; 601 TTF_SizeText(font[map[curmap].textob[o].h], map[curmap].textob[map[curmap].selecteditem].text, &tw,&th); 602 map[curmap].textob[map[curmap].selecteditem].w = tw; 603 /* adjust offsets on all links to/from object */ 604 changestate(S_NONE); 605 sprintf(statustext, "Text #%d resized to match text #%d.",map[curmap].selecteditem,o); 606 drawmap(TRUE); 607 } 608 } 609 } else if (state == S_MATCHX) { 610 if (matchtype == T_OBJECT) { 611 o = objat(event.button.x, event.button.y); 612 if (o == -1) { 613 changestate(S_NONE); 614 sprintf(statustext, "X position match mode aborted."); 615 drawstatusbar(); 616 } else { 617 /* move selected item to match one which was clicked */ 618 /* match middle of objects! */ 619 map[curmap].obj[map[curmap].selecteditem].x = 620 (map[curmap].obj[o].x + (map[curmap].obj[o].w/2)) 621 - 622 (map[curmap].obj[map[curmap].selecteditem].w/2); 623 changestate(S_NONE); 624 sprintf(statustext, "Object #%d X relocated to match object #%d.",map[curmap].selecteditem,o); 625 drawmap(TRUE); 626 } 627 } else if (matchtype == T_TEXT) { 628 o = textat(event.button.x, event.button.y); 629 if (o == -1) { 630 changestate(S_NONE); 631 sprintf(statustext, "X position match mode aborted."); 632 drawstatusbar(); 633 } else { 634 /* move selected item to match one which was clicked */ 635 /* match middle of text */ 636 map[curmap].textob[map[curmap].selecteditem].x = 637 (map[curmap].textob[o].x + (map[curmap].textob[o].w/2)) 638 - 639 (map[curmap].textob[map[curmap].selecteditem].w/2); 640 /* validate */ 641 if (map[curmap].textob[map[curmap].selecteditem].x < 1) map[curmap].textob[map[curmap].selecteditem].x = 1; 642 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; 643 644 changestate(S_NONE); 645 sprintf(statustext, "Text #%d X relocated to match text #%d.",map[curmap].selecteditem,o); 646 drawmap(TRUE); 647 } 648 } 649 } else if (state == S_MATCHY) { 650 if (matchtype == T_OBJECT) { 651 o = objat(event.button.x, event.button.y); 652 if (o == -1) { 653 changestate(S_NONE); 654 sprintf(statustext, "Y position match mode aborted."); 655 drawstatusbar(); 656 } else { 657 /* move selected item to match one which was clicked */ 658 map[curmap].obj[map[curmap].selecteditem].y = 659 (map[curmap].obj[o].y + (map[curmap].obj[o].h / 2)) 660 - 661 map[curmap].obj[map[curmap].selecteditem].h/2; 662 changestate(S_NONE); 663 sprintf(statustext, "Object #%d Y relocated to match object #%d.",map[curmap].selecteditem,o); 664 drawmap(TRUE); 665 } 666 } else if (matchtype == T_TEXT) { 667 o = textat(event.button.x, event.button.y); 668 if (o == -1) { 669 changestate(S_NONE); 670 sprintf(statustext, "Y position match mode aborted."); 671 drawstatusbar(); 672 } else { 673 int curh, copyh; 674 675 curh = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); 676 copyh = TTF_FontHeight(font[map[curmap].textob[o].h]); 677 /* move selected item to match one which was clicked */ 678 map[curmap].textob[map[curmap].selecteditem].y = 679 (map[curmap].textob[o].y + (copyh / 2)) 680 - 681 (curh / 2); 682 683 684 /* validate */ 685 if (map[curmap].textob[map[curmap].selecteditem].y < 1) map[curmap].textob[map[curmap].selecteditem].y = 1; 686 if (map[curmap].textob[map[curmap].selecteditem].y + curh > map[curmap].height) map[curmap].textob[map[curmap].selecteditem].y = map[curmap].height - curh - 1; 687 688 /* match middle of text */ 689 changestate(S_NONE); 690 sprintf(statustext, "Text #%d Y relocated to match text #%d.",map[curmap].selecteditem,o); 691 drawmap(TRUE); 692 } 693 } 694 } else if (state == S_OBJMOVING) { 695 /* has mouse actually moved? */ 696 if ((event.button.x == startx) && (event.button.y == starty)) { 697 /* select the object */ 698 map[curmap].selecteditem = map[curmap].curobj; 699 map[curmap].selecteditemtype = T_OBJECT; 700 changestate(S_NONE); 701 sprintf(statustext, "Object #%d (%s) selected.\n",map[curmap].selecteditem, objtype[map[curmap].obj[map[curmap].selecteditem].type].name); 702 drawmap(TRUE); 703 } else { 704 // actually move the object 705 if (!endobjmove(event.button.x, event.button.y)) { 706 sprintf(statustext, "Object #%d moved to (%d,%d).\n",map[curmap].curobj,event.button.x, event.button.y); 707 } 708 changestate(S_NONE); 709 drawmap(TRUE); 710 711 } 712 } else if (state == S_LINKMOVING) { 713 /* has mouse actually moved? */ 714 if ((event.button.x - screenx == startx) && (event.button.y - screeny == starty)) { 715 /* select the link */ 716 map[curmap].selecteditem = map[curmap].curlink; 717 map[curmap].selecteditemtype = T_LINK; 718 changestate(S_NONE); 719 sprintf(statustext,"Link #%d selected.\n",map[curmap].selecteditem); 720 drawmap(TRUE); 721 } else { 722 // actually move the link 723 endlinkmove(event.button.x, event.button.y); 724 changestate(S_NONE); 725 sprintf(statustext,"Link #%d moved to (%d,%d).\n",map[curmap].curlink,event.button.x, event.button.y); 726 drawmap(TRUE); 727 } 728 } else if (state == S_LINKPOINTMOVE) { 729 /* has mouse actually moved? */ 730 if ((event.button.x == startx) && (event.button.y == starty)) { 731 /* select the link point */ 732 map[curmap].selecteditem = map[curmap].curlink; 733 map[curmap].selecteditemtype = T_LINKPOINT; 734 map[curmap].selectedlinkpoint = map[curmap].curlinkpoint; 735 changestate(S_NONE); 736 sprintf(statustext,"Link #%d point #%d selected.\n",map[curmap].selecteditem,map[curmap].selectedlinkpoint); 737 drawmap(TRUE); 738 } else { 739 // actually move the link 740 endlinkpointmove(event.button.x, event.button.y); 741 changestate(S_NONE); 742 drawmap(TRUE); 743 } 744 } else if (state == S_TEXTMOVING) { 745 /* has mouse actually moved? */ 746 if ((event.button.x == startx) && (event.button.y == starty)) { 747 /* select the object */ 748 map[curmap].selecteditem = map[curmap].curtext; 749 map[curmap].selecteditemtype = T_TEXT; 750 changestate(S_NONE); 751 sprintf(statustext,"Text item #%d selected.\n",map[curmap].selecteditem); 752 drawmap(TRUE); 753 } else { 754 // actually move the text 755 if (!endtextmove(event.button.x, event.button.y)) { 756 sprintf(statustext,"Text item #%d moved to (%d,%d).\n",map[curmap].curtext,event.button.x, event.button.y); 757 } 758 changestate(S_NONE); 759 drawmap(TRUE); 760 761 } 762 } else if (state == S_LINKSRCMOVE) { 763 // actually move the link src endpoint 764 endlinksrcmove(event.button.x, event.button.y); 765 changestate(S_NONE); 766 drawmap(TRUE); 767 } else if (state == S_LINKDSTMOVE) { 768 // actually move the link dst endpoint 769 endlinkdstmove(event.button.x, event.button.y); 770 changestate(S_NONE); 771 drawmap(TRUE); 772 } else if (state == S_ADDOBJ) { 773 /* create a new object */ 774 createobject(map[curmap].selectedtype, event.button.x, event.button.y); 775 drawmap(TRUE); 776 changestate(S_NONE); 777 } else if (state == S_ADDTEXT) { 778 /* start listening for text input */ 779 startx = event.button.x; 780 starty = event.button.y; 781 textanchor = objat(event.button.x,event.button.y); 782 if (textanchor != -1) { 783 startx = map[curmap].obj[textanchor].x; 784 starty = map[curmap].obj[textanchor].y + map[curmap].obj[textanchor].h+3; 785 } 786 updateheight = DEFTEXTH; 787 788 strcpy(text, ""); 789 textpos = text; 790 791 bg = NULL; 792 updatetextcursor(); 793 794 changestate(S_TYPETEXT); 795 } else if (state == S_FILLCOL) { 796 getcolor(screen, event.button.x, event.button.y, &objfillcol); 797 objfillcol.unused |= USECOLOUR; /* clear NOCOLOUR flag */ 798 if (map[curmap].selecteditem != -1) { 799 if (map[curmap].selecteditemtype == T_OBJECT) { 800 map[curmap].obj[map[curmap].selecteditem].fillcol = objfillcol; 801 map[curmap].obj[map[curmap].selecteditem].fillcol.unused |= USECOLOUR; 802 sprintf(statustext, "Fill colour of object #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, objfillcol.r,objfillcol.g,objfillcol.b); 803 } else { 804 sprintf(statustext, "Fill colour selected: R=%d,G=%d,B=%d",objfillcol.r,objfillcol.g,objfillcol.b); 805 } 806 } else { 807 sprintf(statustext, "Fill colour selected: R=%d,G=%d,B=%d",objfillcol.r,objfillcol.g,objfillcol.b); 808 } 809 changestate(S_NONE); 810 drawmap(TRUE); 811 } else if (state == S_FGCOL) { 812 getcolor(screen, event.button.x, event.button.y, &fgcol); 813 if (map[curmap].selecteditem != -1) { 814 int flow = isflow(map[curmap].selecteditem, map[curmap].selecteditemtype); 815 if (map[curmap].selecteditemtype == T_LINK) { 816 map[curmap].olink[map[curmap].selecteditem].col = fgcol; 817 if (flow) { 818 map[curmap].olink[map[curmap].selecteditem].col.unused |= ISFLOW; 819 } 820 sprintf(statustext, "Colour of link #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b); 821 } else if (map[curmap].selecteditemtype == T_TEXT) { 822 map[curmap].textob[map[curmap].selecteditem].c = fgcol; 823 if (flow) { 824 map[curmap].textob[map[curmap].selecteditem].c.unused |= ISFLOW; 825 } 826 sprintf(statustext, "Colour of text item #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b); 827 } else { 828 sprintf(statustext, "Foreground colour selected: R=%d,G=%d,B=%d",fgcol.r,fgcol.g,fgcol.b); 829 } 830 } else { 831 sprintf(statustext, "Foreground colour selected: R=%d,G=%d,B=%d",fgcol.r,fgcol.g,fgcol.b); 832 } 833 changestate(S_NONE); 834 drawmap(TRUE); 835 } else if (state == S_CREATETELE) { 836 int pos; 837 838 if (event.button.y >= 50) { 839 pos = (event.button.y - 50) / (DEFTEXTH*2); 840 pos--; 841 if (pos == -1) { 842 map[curmap].obj[map[curmap].selecteditem].child = pos; 843 sprintf(statustext, "Map link removed."); 844 strcpy(oldstatustext, statustext); 845 setmod(TRUE); 846 changestate(S_NONE); 847 drawmap(TRUE); 848 } else if ((pos+maplistpos) <= (nummaps-1)) { 849 if ((map[curmap].selecteditem != -1) && (map[curmap].selecteditemtype == T_OBJECT)) { 850 if ((pos+maplistpos) != curmap) { 851 map[curmap].obj[map[curmap].selecteditem].child = pos + maplistpos; 852 sprintf(statustext, "Map link created."); 853 strcpy(oldstatustext, statustext); 854 setmod(TRUE); 855 changestate(S_NONE); 856 drawmap(TRUE); 857 } else { 858 seterror(255); 859 sprintf(statustext, "ERROR: Cannot link to current map!"); 860 drawstatusbar(); 861 } 862 } 863 } else { /* mouse is not over a map name */ 864 sprintf(statustext, "Map link creation cancelled."); 865 changestate(S_NONE); 866 drawmap(TRUE); 867 } 868 } else { 869 sprintf(statustext, "Map link creation cancelled."); 870 changestate(S_NONE); 871 drawmap(TRUE); 872 } 873 } 874 875 } else if (isonobox(event.button.x, event.button.y)) { 876 int tempx,tempy; 877 878 tempx = (event.button.x - obox.x) / (obox.gridsize+3); 879 tempy = (event.button.y - obox.y) / (obox.gridsize+3); 880 if (state == S_CHANGEOBJECT) { 881 int seltype; 882 seltype = tempy*obox.gridrowlen + tempx + (obox.pos*3); 883 if (seltype >= numobjtypes) seltype = numobjtypes-1; 884 if (map[curmap].selecteditemtype != T_OBJECT) { 885 seterror(255); 886 sprintf(statustext, "ERROR: Must select an object to change the type of!"); 887 drawstatusbar(); 888 } else if (map[curmap].selecteditem == -1) { 889 seterror(255); 890 sprintf(statustext, "ERROR: Must select an object to change the type of!"); 891 drawstatusbar(); 892 } else { 893 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); 894 map[curmap].obj[map[curmap].selecteditem].type = seltype; 895 state = S_NONE; 896 drawtoolbox(); 897 drawmap(TRUE); 898 } 899 } else { 900 map[curmap].selectedtype = tempy*obox.gridrowlen + tempx + (obox.pos*3); 901 if (map[curmap].selectedtype >= numobjtypes) map[curmap].selectedtype = numobjtypes-1; 902 sprintf(statustext,"Object type '%s' selected.\n",objtype[map[curmap].selectedtype].name); 903 } 904 drawstatusbar(); 905 906 drawobox(); 907 SDL_UpdateRect(screen, obox.x, obox.y, obox.width,obox.height); 908 } else if (isongoback(event.button.x, event.button.y)) { 909 /* go back */ 910 goback(); 911 } else if (isonmapname(event.button.x, event.button.y)) { 912 /* rename current map */ 913 startx = 1; 914 starty = ((screen->h - STATUSH)/2)-2; 915 bg = NULL; 916 strcpy(text, map[curmap].name); 917 textpos = &text[strlen(text)]; 918 changestate(S_MAPNAMING); 919 drawmap(TRUE); 920 break; 921 } else if (isonmapboxchildren(event.button.x, event.button.y)) { 922 if ((state != S_XSCROLL) && (state != S_YSCROLL)) { 923 int pos; 924 int th; 925 926 /* calculate pixel size of mapbox text */ 927 th = TTF_FontHeight(font[MAPBOXTEXTHEIGHT]); 928 /* change to child */ 929 pos = (event.button.y - (mapbox.y+(th*2)+1)) / th; 930 /* adjust for offset if not a special value */ 931 pos += mapbox.offset; 932 if (pos >= numchildren) { 933 seterror(255); 934 sprintf(statustext, "ERROR: Invalid child map %d (max is %d).",pos,numchildren); 935 drawstatusbar(); 936 } else { 937 drillto(children[pos]); 938 } 939 } 940 break; 941 } else if (isontoolbox(event.button.x, event.button.y)) { 942 int tempx,tempy, selection; 943 int boxy; 944 945 tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); 946 tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); 947 948 boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); 949 950 /* are we in a colour selection state? */ 951 if (state == S_FGCOL) { 952 /* set fgcol to black */ 953 fgcol = black; 954 sprintf(statustext, "Foreground colour selected: R=0,G=0,B=0"); 955 changestate(S_NONE); 956 drawmap(TRUE); 957 break; 958 } else if (state == S_FILLCOL) { 959 /* set bgcol to 'nothing' */ 960 objfillcol = black; 961 objfillcol.unused &= ~(USECOLOUR); 962 if (map[curmap].selecteditem != -1) { 963 if (map[curmap].selecteditemtype == T_OBJECT) { 964 map[curmap].obj[map[curmap].selecteditem].fillcol = black; 965 map[curmap].obj[map[curmap].selecteditem].fillcol.unused &= ~(USECOLOUR); 966 sprintf(statustext, "Fill colour of object #%d removed.", map[curmap].selecteditem); 967 } else { 968 sprintf(statustext, "Fill colour removed."); 969 } 970 } else { 971 sprintf(statustext, "Fill colour removed."); 972 } 973 changestate(S_NONE); 974 drawmap(TRUE); 975 break; 976 } 977 978 selection = tempy*toolbox.gridrowlen + tempx; 979 switch (selection) { 980 case TB_POINTER: 981 /* special case - update sbar */ 982 sprintf(statustext, "Selection mode entered."); 983 drawstatusbar(); 984 changestate(S_NONE); 985 map[curmap].curobj = -1; 986 break; 987 case TB_ADDOBJ: 988 changestate(S_ADDOBJ); 989 if (map[curmap].selectedtype < 0) map[curmap].selectedtype = 0; 990 break; 991 case TB_ADDTEXT: 992 changestate(S_ADDTEXT); 993 break; 994 case TB_COPY: 995 copy(); 996 break; 997 case TB_FLOW: 998 if (showflows) { 999 setinfo(255); 1000 showflows = FALSE; 1001 sprintf(statustext, "Traffic flows hidden."); 1002 } else { 1003 setinfo(255); 1004 sprintf(statustext, "Traffic flows displayed."); 1005 showflows = TRUE; 1006 } 1007 drawtoolbox(); 1008 drawmap(TRUE); 1009 break; 1010 case TB_GRID: 1011 togglegrid(); 1012 drawmap(TRUE); 1013 break; 1014 case TB_NEW: 1015 if (readonly) { 1016 seterror(255); 1017 sprintf(statustext, "Cannot delete maps in read-only mode."); 1018 drawstatusbar(); 1019 break; 1020 1021 } 1022 tmod = SDL_GetModState(); 1023 if (!(mod & KMOD_SHIFT)) { 1024 seterror(255); 1025 sprintf(statustext, "Must hold down SHIFT to start new project (avoids accidental loss of data)!"); 1026 drawstatusbar(); 1027 break; 1028 } 1029 initvars(); 1030 changestate(S_NONE); 1031 setinfo(255); 1032 sprintf(statustext, "All maps cleared."); 1033 sprintf(oldstatustext, statustext); 1034 1035 drawmap(TRUE); 1036 break; 1037 case TB_LINESTYLE: 1038 if (map[curmap].selecteditemtype == T_LINK) { 1039 if (map[curmap].selecteditem != -1) { 1040 int si = map[curmap].selecteditem; 1041 /* TODO: add arrow */ 1042 /* where are we? */ 1043 if (event.button.y <= (boxy + 9)) { 1044 /* clear thickness */ 1045 map[curmap].olink[si].style &= 0xFFFF00; 1046 /* set to default */ 1047 map[curmap].olink[si].style |= defthickness; 1048 } else if (event.button.y <= (boxy + 19)) { 1049 /* clear style */ 1050 map[curmap].olink[si].style &= 0xFF00FF; 1051 /* set to default */ 1052 map[curmap].olink[si].style |= (defstyle << 8); 1053 } else { 1054 /* clear arrow */ 1055 map[curmap].olink[si].style &= 0x00FFFF; 1056 /* set to default */ 1057 map[curmap].olink[si].style |= (defarrow << 16); 1058 } 1059 setmod(TRUE); 1060 drawmap(TRUE); 1061 } else { 1062 seterror(255); 1063 sprintf(statustext, "No link selected!"); 1064 } 1065 } else { 1066 seterror(255); 1067 sprintf(statustext, "No link selected!"); 1068 } 1069 drawstatusbar(); 1070 break; 1071 case TB_MATCHSIZE: 1072 if (map[curmap].selecteditem != -1) { 1073 switch (map[curmap].selecteditemtype) { 1074 case T_OBJECT: 1075 case T_TEXT: 1076 matchtype = map[curmap].selecteditemtype; 1077 changestate(S_MATCHSIZE); 1078 drawmap(TRUE); 1079 break; 1080 } 1081 } 1082 break; 1083 case TB_MATCHPOS: 1084 if (map[curmap].selecteditem != -1) { 1085 switch (map[curmap].selecteditemtype) { 1086 case T_OBJECT: 1087 case T_TEXT: 1088 matchtype = map[curmap].selecteditemtype; 1089 changestate(S_MATCHX); 1090 drawmap(TRUE); 1091 break; 1092 } 1093 } 1094 break; 1095 case TB_PASTE: 1096 paste(); 1097 break; 1098 case TB_FGCOL: 1099 /* change selected item to match fgcol */ 1100 if (map[curmap].selecteditem != -1) { 1101 int flow = isflow(map[curmap].selecteditem, map[curmap].selecteditemtype); 1102 if (map[curmap].selecteditemtype == T_LINK) { 1103 map[curmap].olink[map[curmap].selecteditem].col = fgcol; 1104 /* maintain flow attribute */ 1105 if (flow) { 1106 map[curmap].olink[map[curmap].selecteditem].col.unused |= ISFLOW; 1107 } 1108 setmod(TRUE); 1109 sprintf(statustext, "Colour of link #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b); 1110 } else if (map[curmap].selecteditemtype == T_TEXT) { 1111 map[curmap].textob[map[curmap].selecteditem].c = fgcol; 1112 /* maintain flow attribute */ 1113 if (flow) { 1114 map[curmap].textob[map[curmap].selecteditem].c.unused |= ISFLOW; 1115 } 1116 setmod(TRUE); 1117 sprintf(statustext, "Colour of text item #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, fgcol.r,fgcol.g,fgcol.b); 1118 } else { 1119 seterror(255); 1120 sprintf(statustext, "No object selected! (use RMB to select new foreground colour)"); 1121 } 1122 } else { 1123 seterror(255); 1124 sprintf(statustext, "No object selected! (use RMB to select new foreground colour)"); 1125 } 1126 drawmap(TRUE); 1127 break; 1128 case TB_FILLCOL: 1129 if (map[curmap].selecteditem != -1) { 1130 if (map[curmap].selecteditemtype == T_OBJECT) { 1131 map[curmap].obj[map[curmap].selecteditem].fillcol = objfillcol; 1132 map[curmap].obj[map[curmap].selecteditem].fillcol.unused = objfillcol.unused; 1133 setmod(TRUE); 1134 if (objfillcol.unused & USECOLOUR) { 1135 sprintf(statustext, "Fill colour of object #%d changed to R=%d,G=%d,B=%d",map[curmap].selecteditem, objfillcol.r,objfillcol.g,objfillcol.b); 1136 } else { 1137 sprintf(statustext, "Fill colour of object #%d removed.",map[curmap].selecteditem); 1138 } 1139 } else { 1140 seterror(255); 1141 sprintf(statustext, "No object selected! (use RMB to select new fill colour)"); 1142 } 1143 } else { 1144 seterror(255); 1145 sprintf(statustext, "No object selected! (use RMB to select new fill colour)"); 1146 } 1147 drawmap(TRUE); 1148 break; 1149 case TB_DELETEMAP: 1150 /* safety - must hold down SHIFT to delete maps */ 1151 1152 if (readonly) { 1153 seterror(255); 1154 sprintf(statustext, "Cannot delete maps in read-only mode."); 1155 drawstatusbar(); 1156 break; 1157 1158 } 1159 tmod = SDL_GetModState(); 1160 if (!(mod & KMOD_SHIFT)) { 1161 seterror(255); 1162 sprintf(statustext, "Must hold down SHIFT to delete maps (avoids accidental loss of data)!"); 1163 drawstatusbar(); 1164 break; 1165 } 1166 if (curmap == 0) { 1167 seterror(255); 1168 sprintf(statustext, "Cannot delete toplevel map!"); 1169 drawstatusbar(); 1170 break; 1171 } 1172 delmap = curmap; 1173 /* any children in curent map? */ 1174 found = FALSE; 1175 for (n = 0; n < map[delmap].numobjects; n++) { 1176 if (map[delmap].obj[n].child != -1) { 1177 found = TRUE; 1178 break; 1179 } 1180 } 1181 if (found) { 1182 seterror(255); 1183 sprintf(statustext, "Cannot delete a map with children."); 1184 drawstatusbar(); 1185 break; 1186 } 1187 /* shuffle numbers on all other objects */ 1188 for (n = 0; n < nummaps; n++) { 1189 int o; 1190 for (o = 0; o < map[n].numobjects; o++) { 1191 if (map[n].obj[o].child == delmap) { 1192 map[n].obj[o].child = -1; 1193 } else if (map[n].obj[o].child > delmap) { 1194 map[n].obj[o].child--; 1195 } 1196 } 1197 } 1198 /* move all higher maps down by one */ 1199 for (n = delmap; n < (nummaps-1); n++) { 1200 map[n] = map[n+1]; 1201 } 1202 nummaps--; 1203 /* move far enough back to avoid all occurences of this map */ 1204 found = FALSE; 1205 for (n = 0; n < (numhistory-1); n++) { 1206 if (history[n+1] == delmap) { 1207 if (history[n] > delmap) { 1208 changemap(history[n] - 1); 1209 } else { 1210 changemap(history[n]); 1211 } 1212 numhistory = n+1; 1213 found = TRUE; 1214 break; 1215 } 1216 } 1217 if (!found) { 1218 goback(); 1219 setinfo(255); 1220 sprintf(statustext, "Deleted map #%d.\n",delmap); 1221 } 1222 /* fix history array */ 1223 for (n = 0; n < numhistory; n++) { 1224 if (history[n] > delmap) { 1225 history[n]--; 1226 } 1227 } 1228 drawmap(TRUE); 1229 break; 1230 case TB_CREATETELE: 1231 if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) { 1232 setinfo(255); 1233 sprintf(statustext,"Select destination map to link to..."); 1234 changestate(S_CREATETELE); 1235 drawmap(TRUE); 1236 } else { 1237 seterror(255); 1238 sprintf(statustext,"Cannot create map link - no object selected!"); 1239 drawstatusbar(); 1240 } 1241 break; 1242 1243 case TB_DRILLDOWN: 1244 if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) { 1245 drillto(map[curmap].obj[map[curmap].selecteditem].child); 1246 } else { 1247 seterror(255); 1248 sprintf(statustext,"Cannot drill down - no object selected!"); 1249 drawstatusbar(); 1250 } 1251 break; 1252 case TB_SAVE: 1253 startx = 1; 1254 starty = ((screen->h - STATUSH)/2)-2; 1255 bg = NULL; 1256 strcpy(text, currentfilename); 1257 textpos = &text[strlen(text)]; 1258 changestate(S_SAVING); 1259 drawmap(TRUE); 1260 break; 1261 case TB_LOAD: 1262 startx = 1; 1263 starty = ((screen->h - STATUSH)/2)-2; 1264 bg = NULL; 1265 strcpy(text, currentfilename); 1266 textpos = &text[strlen(text)]; 1267 changestate(S_LOADING); 1268 drawmap(TRUE); 1269 break; 1270 1271 } 1272 drawtoolbox(); 1273 } /* end if is on map */ 1274 } else if ((event.button.button == SDL_BUTTON_MIDDLE) || 1275 ((event.button.button == SDL_BUTTON_LEFT) && (mod & KMOD_CTRL))) { 1276 if (state == S_DRAWLINK) { 1277 // finish drawing link 1278 o = objat(event.button.x + screenx, event.button.y + screeny); 1279 if ((o != -1) && (o != startobj)) { 1280 endobj = o; 1281 endlink(event.button.x,event.button.y); 1282 changestate(S_NONE); 1283 drawmap(TRUE); 1284 } else { 1285 pasteline(screen,linebg); 1286 sprintf(statustext,"Aborting link #%d.\n", map[curmap].numlinks); 1287 drawstatusbar(); 1288 } 1289 changestate(S_NONE); 1290 } else if (state == S_NONE) { 1291 /* are we on a link? if so, add a point to it */ 1292 o = getlinkat(event.button.x + screenx, event.button.y + screeny); 1293 if (o != -1) { 1294 addlinkpoint(o, event.button.x+screenx, event.button.y+screeny); 1295 /* select the link */ 1296 map[curmap].selecteditemtype = T_LINK; 1297 map[curmap].selecteditem = o; 1298 drawmap(TRUE); 1299 } 1300 } 1301 1302 1303 1304 } else if (event.button.button == SDL_BUTTON_RIGHT) { 1305 if (state == S_RESIZING) { 1306 // end resize 1307 endresize(event.button.x, event.button.y); 1308 changestate(S_NONE); 1309 drawmap(TRUE); 1310 } else if (state == S_TEXTRESIZING) { 1311 // end text resize 1312 endtextresize(event.button.x, event.button.y); 1313 changestate(S_NONE); 1314 } 1315 /* check for right click on toolbox */ 1316 if (isontoolbox(event.button.x, event.button.y)) { 1317 int tempx,tempy, selection,boxy; 1318 1319 tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); 1320 tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); 1321 boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); 1322 selection = tempy*toolbox.gridrowlen + tempx; 1323 switch (selection) { 1324 case TB_ADDOBJ: 1325 if (map[curmap].selecteditemtype != T_OBJECT) { 1326 seterror(255); 1327 sprintf(statustext, "Must select an object to change the type of first!"); 1328 drawstatusbar(); 1329 } else if (map[curmap].selecteditem == -1) { 1330 seterror(255); 1331 sprintf(statustext, "Must select an object to change the type of first!"); 1332 drawstatusbar(); 1333 } else { 1334 changestate(S_CHANGEOBJECT); 1335 } 1336 break; 1337 case TB_ADDTEXT: 1338 if (state == S_NONE) { 1339 if ( (map[curmap].selecteditemtype == T_TEXT) && 1340 (map[curmap].selecteditem != -1) ){ 1341 startedittext(map[curmap].selecteditem); 1342 } else { 1343 seterror(255); 1344 sprintf(statustext, "Cannot edit text - no text item selected!"); 1345 drawstatusbar(); 1346 } 1347 } 1348 break; 1349 case TB_GRID: 1350 changegridsize(); 1351 drawmap(TRUE); 1352 break; 1353 case TB_FLOW: 1354 oldshowflows = showflows; 1355 showflows = TRUE; 1356 drawtoolbox(); 1357 changestate(S_DRAWFLOW); 1358 drawmap(TRUE); 1359 break; 1360 case TB_FGCOL: 1361 changestate(S_FGCOL); 1362 drawmap(TRUE); 1363 break; 1364 case TB_FILLCOL: 1365 changestate(S_FILLCOL); 1366 drawmap(TRUE); 1367 break; 1368 case TB_MATCHPOS: /* match y */ 1369 if (map[curmap].selecteditem != -1) { 1370 switch (map[curmap].selecteditemtype) { 1371 case T_OBJECT: 1372 case T_TEXT: 1373 matchtype = map[curmap].selecteditemtype; 1374 changestate(S_MATCHY); 1375 drawmap(TRUE); 1376 break; 1377 } 1378 } 1379 break; 1380 case TB_LINESTYLE: 1381 /* figure out where in the box we are */ 1382 if (event.button.y <= (boxy + 9)) { 1383 changelinethickness(1); 1384 } else if (event.button.y <= (boxy + 19)) { 1385 changelinestyle(1); 1386 } else { 1387 changelinearrow(1); 1388 } 1389 drawstatusbar(); 1390 break; 1391 } 1392 } 1393 } 1394 break; 1395 case SDL_MOUSEMOTION: 1396 switch (state) { 1397 case S_OBJMOVING: 1398 updatemoveshadow(event.button.x, event.button.y); 1399 break; 1400 case S_RESIZING: 1401 updateresizeshadow(event.button.x, event.button.y); 1402 break; 1403 case S_DRAWLINK: 1404 updatelinkshadow(event.button.x, event.button.y); 1405 break; 1406 case S_TEXTMOVING: 1407 updatetextshadow(event.button.x, event.button.y); 1408 break; 1409 case S_TEXTRESIZING: 1410 updateresizetextshadow(event.button.x, event.button.y); 1411 break; 1412 case S_LINKPOINTMOVE: 1413 updatelinkpointshadow(event.button.x, event.button.y); 1414 break; 1415 case S_NONE: 1416 /* has mouse moved since last time? */ 1417 mousepos = getmousepos(event.button.x, event.button.y); 1418 if ((mousepos != oldmousepos ) || (mousepos== MP_TOOLBOX)) { 1419 /* rollovers */ 1420 if (mousepos == MP_TOOLBOX) { 1421 SDL_Rect area; 1422 int tempx,tempy, selection; 1423 int boxy; 1424 1425 if (!rollover) strcpy(oldstatustext, statustext); 1426 rollover = TRUE; 1427 1428 /* determine which button we're over */ 1429 tempx = (event.button.x - toolbox.x) / (toolbox.gridsize+3); 1430 tempy = (event.button.y - toolbox.y) / (toolbox.gridsize+3); 1431 1432 boxy = toolbox.y + (tempy*(toolbox.gridsize+3)); 1433 1434 selection = tempy*toolbox.gridrowlen + tempx; 1435 /* replace old button */ 1436 if (toolbg != NULL) { 1437 SDL_Rect area; 1438 1439 1440 if (oldselection >= 0) { 1441 if (dontpaste == FALSE) { 1442 area.x = toolbox.x + ((oldselection % 3 )*(toolbox.gridsize+3)); 1443 area.y = toolbox.y + ((oldselection / 3)*(toolbox.gridsize+3)); 1444 area.w = toolbox.gridsize; 1445 area.h = toolbox.gridsize; 1446 SDL_BlitSurface(toolbg, NULL, screen, &area); 1447 SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); 1448 } else { 1449 dontpaste = FALSE; 1450 } 1451 } 1452 SDL_FreeSurface(toolbg); 1453 toolbg = NULL; 1454 } 1455 /* copy background of this button */ 1456 if (selection <= TB_SAVE) { 1457 toolbg = SDL_CreateRGBSurface(SDL_SWSURFACE,toolbox.gridsize+3, toolbox.gridsize+3, 1458 screen->format->BitsPerPixel, screen->format->Rmask, 1459 screen->format->Gmask,screen->format->Bmask, 1460 screen->format->Amask); 1461 area.x = toolbox.x + ((selection % 3 )*(toolbox.gridsize+3)); 1462 area.y = toolbox.y + ((selection / 3)*(toolbox.gridsize+3)); 1463 area.w = toolbox.gridsize+1; 1464 area.h = toolbox.gridsize+1; 1465 SDL_BlitSurface(screen,&area, toolbg, 0); 1466 1467 /* draw highlight */ 1468 if (selection == TB_LINESTYLE) { 1469 SDL_Rect sarea; 1470 1471 if (event.button.y <= (boxy + 9)) { 1472 sarea.x = 0; 1473 sarea.y = 0; 1474 sarea.w = toolbox.gridsize; 1475 sarea.h = 11; 1476 area.h = 11; 1477 area.y += 1; 1478 } else if (event.button.y <= (boxy + 19)) { 1479 sarea.x = 0; 1480 sarea.y = 0; 1481 sarea.w = toolbox.gridsize; 1482 sarea.h = 10; 1483 area.h = 10; 1484 area.y += 12; 1485 } else { 1486 sarea.x = 0; 1487 sarea.y = 0; 1488 sarea.w = toolbox.gridsize; 1489 sarea.h = 8; 1490 area.h = 8; 1491 area.y += 21; 1492 } 1493 SDL_BlitSurface(toolhilite, &sarea, screen, &area); 1494 } else { 1495 SDL_BlitSurface(toolhilite, NULL, screen, &area); 1496 } 1497 1498 SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); 1499 } 1500 1501 if (selection != oldselection) { 1502 switch (selection) { 1503 case TB_POINTER: 1504 sprintf(statustext, "LMB = Enter object selection mode"); 1505 drawstatusbar(); 1506 break; 1507 case TB_ADDOBJ: 1508 sprintf(statustext, "LMB = Add an object to the map, RMB = Change object type"); 1509 drawstatusbar(); 1510 break; 1511 case TB_ADDTEXT: 1512 sprintf(statustext, "LMB (on map) = Add text to the map, LMB (on object) = Add text to an object"); 1513 drawstatusbar(); 1514 break; 1515 case TB_COPY: 1516 sprintf(statustext, "LMB = Copy the current object/text/map"); 1517 drawstatusbar(); 1518 break; 1519 case TB_PASTE: 1520 sprintf(statustext, "LMB = Paste the current copy buffer"); 1521 drawstatusbar(); 1522 break; 1523 case TB_GRID: 1524 sprintf(statustext, "LMB = Toggle grid on/off, RMB = Change grid size"); 1525 drawstatusbar(); 1526 break; 1527 case TB_FGCOL: 1528 sprintf(statustext, "LMB = Apply default foreground colour to current selection, RMB = Change default foreground colour"); 1529 drawstatusbar(); 1530 break; 1531 case TB_FILLCOL: 1532 sprintf(statustext, "LMB = Apply default fill colour to current selection, RMB = Change default fill colour"); 1533 drawstatusbar(); 1534 break; 1535 case TB_LINESTYLE: 1536 if (event.button.y <= (boxy + 9)) { 1537 sprintf(statustext, "LMB = Apply default thickness to current line, RMB = Change default line thickness"); 1538 } else if (event.button.y <= (boxy + 19)) { 1539 sprintf(statustext, "LMB = Apply default style to current line, RMB = Change default line style"); 1540 } else { 1541 sprintf(statustext, "LMB = Apply default arrowhead type to current line, RMB = Change default arrowhead type"); 1542 } 1543 drawstatusbar(); 1544 break; 1545 case TB_MATCHSIZE: 1546 sprintf(statustext, "LMB = Match size of current selection to next item clicked"); 1547 drawstatusbar(); 1548 break; 1549 case TB_MATCHPOS: 1550 sprintf(statustext, "LMB = Match horizontal position of currently selected item to next item clicked, RMB = match vertical position"); 1551 drawstatusbar(); 1552 break; 1553 case TB_FLOW: 1554 sprintf(statustext, "LMB = Toggle display of traffic flows, RMB = Enter traffic flow definition mode"); 1555 drawstatusbar(); 1556 break; 1557 case TB_DRILLDOWN: 1558 sprintf(statustext, "LMB = Drill down to create new map under current object"); 1559 drawstatusbar(); 1560 break; 1561 case TB_CREATETELE: 1562 sprintf(statustext, "LMB = Set destination map for when current object is double-clicked"); 1563 drawstatusbar(); 1564 break; 1565 case TB_DELETEMAP: 1566 sprintf(statustext, "LMB = Delete current map (hold down SHIFT to confirm)"); 1567 drawstatusbar(); 1568 break; 1569 case TB_NEW: 1570 sprintf(statustext, "LMB = Delete ALL maps and start a fresh project (hold SHIFT to confirm)"); 1571 drawstatusbar(); 1572 break; 1573 case TB_LOAD: 1574 sprintf(statustext, "LMB = Load a new map"); 1575 drawstatusbar(); 1576 break; 1577 case TB_SAVE: 1578 sprintf(statustext, "LMB = Save the current map to disk (will automatically export based on extensions of BMP/PNG/SVG)"); 1579 drawstatusbar(); 1580 break; 1581 default: 1582 break; 1583 } 1584 } 1585 oldselection = selection; 1586 } else if (mousepos == MP_MAPBOXNAME) { 1587 if (!rollover) strcpy(oldstatustext, statustext); 1588 rollover = TRUE; 1589 sprintf(statustext, "LMB = Rename the current map."); 1590 drawstatusbar(); 1591 } else if (mousepos == MP_MAPBOXCHILDREN) { 1592 if (!rollover) strcpy(oldstatustext, statustext); 1593 rollover = TRUE; 1594 sprintf(statustext, "LMB = Drill down into a submap (blue text indicates maps already in the map history)."); 1595 drawstatusbar(); 1596 } else if (mousepos == MP_OBJECTBOX) { 1597 if (!rollover) strcpy(oldstatustext, statustext); 1598 rollover = TRUE; 1599 sprintf(statustext, "LMB = Select a new object type."); 1600 drawstatusbar(); 1601 } else { 1602 strcpy(statustext, oldstatustext); 1603 strcpy(oldstatustext, ""); 1604 drawstatusbar(); 1605 rollover = FALSE; 1606 } 1607 } 1608 oldmousepos = mousepos; 1609 break; 1610 1611 } 1612 /* scrollbar drags */ 1613 mb = SDL_GetMouseState(&mx,&my); 1614 //if (isonxscrollbar(mx,my)) { 1615 if (state == S_XSCROLL) { 1616 if (mb & SDL_BUTTON(1)) { /* if lmb is depressed */ 1617 screenx = (((double)event.button.x / (double)(screen->w - SIDEBARW)) * map[curmap].width) 1618 - ((screen->w - SIDEBARW)/2); 1619 1620 validatescreenpos(); 1621 drawxscrollbar(); 1622 } 1623 } 1624 //if (isonyscrollbar(mx,my)) { 1625 if (state == S_YSCROLL) { 1626 if (mb & SDL_BUTTON(1)) { /* if lmb is depressed */ 1627 screeny = (((double)event.button.y / (double)(screen->h - STATUSH - SBSIZE)) * map[curmap].height) 1628 - ((screen->h - STATUSH - SBSIZE)/2); 1629 1630 validatescreenpos(); 1631 drawyscrollbar(); 1632 } 1633 } 1634 break; 1635 case SDL_QUIT: 1636 if (modified) { 1637 strcpy(text, "Changes not saved - really quit?"); 1638 changestate(S_REALLYQUIT); 1639 drawmap(TRUE); 1640 } else { 1641 done = TRUE; 1642 } 1643 break; 1644 case SDL_VIDEOEXPOSE: 1645 /* redraw screen */ 1646 drawscreen(); 1647 break; 1648 case SDL_KEYDOWN: 1649 c = event.key.keysym.unicode & 0x7F; 1650 c2 = event.key.keysym.sym; 1651 mod = SDL_GetModState(); 1652 /* state independant */ 1653 if (mod & KMOD_SHIFT) { 1654 if ((c >= 'a') && (c <= 'z')) { 1655 c -= 32; 1656 } else if (c == '1') { 1657 c = '!'; 1658 } else if (c == '2') { 1659 c = '@'; 1660 } else if (c == '3') { 1661 c = '#'; 1662 } else if (c == '4') { 1663 c = '$'; 1664 } else if (c == '5') { 1665 c = '%'; 1666 } else if (c == '6') { 1667 c = '^'; 1668 } else if (c == '7') { 1669 c = '&'; 1670 } else if (c == '8') { 1671 c = '*'; 1672 } else if (c == '9') { 1673 c = '('; 1674 } else if (c == '0') { 1675 c = ')'; 1676 } else if (c == '-') { 1677 c = '_'; 1678 } else if (c == '=') { 1679 c = '+'; 1680 } else if (c == '\\') { 1681 c = '|'; 1682 } else if (c == ';') { 1683 c = ':'; 1684 } else if (c == '\'') { 1685 c = '"'; 1686 } else if (c == ',') { 1687 c = '<'; 1688 } else if (c == '.') { 1689 c = '>'; 1690 } else if (c == '/') { 1691 c = '?'; 1692 } 1693 } 1694 /* state dependant */ 1695 if ((state == S_TYPETEXT) || (state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING) || (state == S_EDITTEXT) || (state == S_SEARCH)) { 1696 if ((c2 == 'u') && (mod & KMOD_CTRL)) { 1697 // delete from start to text pos 1698 strcpy(text, textpos); 1699 //text[0] = '\0'; 1700 textpos = text; 1701 updatetextcursor(); 1702 } else if ((c2 == 'k') && (mod & KMOD_CTRL)) { 1703 // delete from here to end 1704 *textpos = '\0'; 1705 updatetextcursor(); 1706 } else if ((c2 == 'a') && (mod & KMOD_CTRL)) { 1707 // go to start of text 1708 textpos = text; 1709 updatetextcursor(); 1710 } else if ((c2 == 'e') && (mod & KMOD_CTRL)) { 1711 // go to end of text 1712 textpos = &text[strlen(text)]; 1713 updatetextcursor(); 1714 } else if ((c >= FIRSTLET) && (c <= LASTLET)) { 1715 // add onto end of text 1716 char temptext[2]; 1717 char endbit[BUFLEN]; 1718 // remember from here until end 1719 if (textpos) { 1720 strcpy(endbit, textpos); 1721 } else { 1722 endbit[0] = '\0'; 1723 } 1724 // end here 1725 *textpos = '\0'; 1726 // append char 1727 sprintf(temptext, "%c", c); 1728 strcat(text, temptext); 1729 // move cursor to end of appended bit 1730 textpos = &text[strlen(text)]; 1731 // append end bit 1732 if (strlen(endbit) > 0) { 1733 strcat(text, endbit); 1734 } 1735 // 1736 updatetextcursor(); 1737 } else if (c2 == SDLK_LEFT) { 1738 // move cursor 1739 if (textpos != text) textpos--; 1740 updatetextcursor(); 1741 } else if (c2 == SDLK_RIGHT) { 1742 if (textpos != &text[strlen(text)]) textpos++; 1743 updatetextcursor(); 1744 } else if ((c2 == SDLK_ESCAPE) || 1745 ((c2 == 'g') && (mod & KMOD_CTRL)) ) { 1746 sprintf(statustext, "Aborted."); 1747 changestate(S_NONE); 1748 drawmap(TRUE); 1749 } else if (c == ' ') { 1750 // add onto end of text 1751 char endbit[BUFLEN]; 1752 // remember from here until end 1753 strcpy(endbit, textpos); 1754 // end here 1755 *textpos = '\0'; 1756 // append char 1757 strcat(text, " "); 1758 // move cursor to end of appended bit 1759 textpos = &text[strlen(text)]; 1760 // append end bit 1761 strcat(text, endbit); 1762 updatetextcursor(); 1763 } else if (c2 == SDLK_BACKSPACE) { 1764 // remove last charater 1765 if (textpos != text) { 1766 strcpy(textpos-1, textpos); 1767 } 1768 //text[strlen(text)-1] = '\0'; 1769 textpos--; 1770 updatetextcursor(); 1771 } else if (c == 13) { /* enter */ 1772 if (state == S_TYPETEXT) { 1773 endtext(); 1774 } else if (state == S_EDITTEXT) { 1775 endtextedit(); 1776 } else if (state == S_SAVING) { 1777 savemap(); 1778 changestate(S_NONE); 1779 drawmap(TRUE); 1780 } else if (state == S_LOADING) { 1781 loadmap(); 1782 changestate(S_NONE); 1783 drawmap(TRUE); 1784 } else if (state == S_SEARCH) { 1785 changestate(S_NONE); 1786 if (dosearch()) { 1787 seterror(255); 1788 sprintf(statustext, "Not found: '%s'",searchtext); 1789 setsearchflash(0); 1790 } else { 1791 setinfo(255); 1792 sprintf(statustext, "Found '%s' in text object #%d (map '%s')",searchtext, map[curmap].selecteditem, map[curmap].name); 1793 setsearchflash(255); 1794 } 1795 drawmap(TRUE); 1796 } else if (state == S_MAPNAMING) { 1797 /* rename map */ 1798 strcpy(map[curmap].name,text); 1799 changestate(S_NONE); 1800 setinfo(255); 1801 sprintf(statustext, "Map #%d renamed to '%s'.",curmap,map[curmap].name); 1802 drawmap(TRUE); 1803 } 1804 } 1805 } else { 1806 if (c2 == SDLK_HOME) { 1807 screenx = 0; 1808 screeny = 0; 1809 drawmap(TRUE); 1810 } 1811 if (c2 == SDLK_END) { 1812 screenx = map[curmap].width - (screen->w-SIDEBARW); 1813 screeny = map[curmap].height - (screen->h-STATUSH); 1814 drawmap(TRUE); 1815 } 1816 if (c == 'a') { /* add map[curmap].object */ 1817 if (state == S_NONE) { 1818 changestate(S_ADDOBJ); 1819 } 1820 } 1821 if (c == '/') { /* search/find */ 1822 if (state == S_NONE) { 1823 startx = 1; 1824 starty = ((screen->h-STATUSH)/2)-2; 1825 bg = NULL; 1826 strcpy(text, ""); 1827 textpos = text; 1828 changestate(S_SEARCH); 1829 drawmap(TRUE); 1830 } 1831 } 1832 if (c == 'n') { /* find next */ 1833 changestate(S_NONE); 1834 if (dosearchnext()) { 1835 seterror(255); 1836 sprintf(statustext, "Not foundnext: '%s'",searchtext); 1837 setsearchflash(0); 1838 } else { 1839 setinfo(255); 1840 sprintf(statustext, "Foundnext %s'%s' in text object #%d (map '%s')",searchwrap ? "(wrapped) " : "",searchtext, map[curmap].selecteditem, map[curmap].name); 1841 setsearchflash(255); 1842 } 1843 drawmap(TRUE); 1844 } 1845 if (c == 'm') { /* modify object type */ 1846 if (state == S_NONE) { 1847 changestate(S_CHANGEOBJECT); 1848 } 1849 } 1850 if (c == 't') { /* add text */ 1851 if (state == S_NONE) { 1852 changestate(S_ADDTEXT); 1853 } 1854 } 1855 if ((c == 'e') || (c2 == SDLK_F2)) { /* edit current text */ 1856 if (state == S_NONE) { 1857 if ( (map[curmap].selecteditemtype == T_TEXT) && 1858 (map[curmap].selecteditem != -1) ){ 1859 startedittext(map[curmap].selecteditem); 1860 } else { 1861 seterror(255); 1862 sprintf(statustext, "Cannot edit text - no text item selected!"); 1863 drawstatusbar(); 1864 } 1865 } 1866 } 1867 if (c == 's') { /* save */ 1868 startx = 1; 1869 starty = ((screen->h-STATUSH)/2)-2; 1870 bg = NULL; 1871 strcpy(text, currentfilename); 1872 textpos = &text[strlen(text)]; 1873 changestate(S_SAVING); 1874 drawmap(TRUE); 1875 } 1876 if ((c == 'l') || (c == 'o')) { /* load, open */ 1877 startx = 1; 1878 starty = ((screen->h-STATUSH)/2)-2; 1879 bg = NULL; 1880 strcpy(text, currentfilename); 1881 textpos = &text[strlen(text)]; 1882 changestate(S_LOADING); 1883 drawmap(TRUE); 1884 } 1885 if ((c == ',') || (c == 'q')) { /* scroll object box up */ 1886 if (state == S_CREATETELE) { 1887 scrollmaplist(-1); 1888 } else { 1889 scrollobox(-1); 1890 } 1891 } 1892 if ((c == '.') || (c == 'w')) { /* scroll object box down */ 1893 if (state == S_CREATETELE) { 1894 scrollmaplist(1); 1895 } else { 1896 scrollobox(1); 1897 } 1898 } 1899 if ((c == '<') || (c == 'Q')) { /* scroll object box up */ 1900 if (state == S_CREATETELE) { 1901 scrollmaplist(-20); 1902 } else { 1903 scrollobox(-OBOXPAGESIZE); 1904 } 1905 } 1906 if ((c == '>') || (c == 'W')) { /* scroll object box down */ 1907 if (state == S_CREATETELE) { 1908 scrollmaplist(20); 1909 } else { 1910 scrollobox(OBOXPAGESIZE); 1911 } 1912 } 1913 if (c == 'x') { 1914 if (map[curmap].selecteditem != -1) { 1915 switch (map[curmap].selecteditemtype) { 1916 case T_OBJECT: 1917 case T_TEXT: 1918 matchtype = map[curmap].selecteditemtype; 1919 changestate(S_MATCHX); 1920 drawmap(TRUE); 1921 break; 1922 } 1923 } 1924 } 1925 if (c == 'y') { 1926 if (map[curmap].selecteditem != -1) { 1927 switch (map[curmap].selecteditemtype) { 1928 case T_OBJECT: 1929 case T_TEXT: 1930 matchtype = map[curmap].selecteditemtype; 1931 changestate(S_MATCHY); 1932 drawmap(TRUE); 1933 break; 1934 } 1935 } 1936 } 1937 if (c == 'b') { 1938 if (map[curmap].selecteditem != -1) { 1939 switch (map[curmap].selecteditemtype) { 1940 case T_OBJECT: 1941 case T_TEXT: 1942 matchtype = map[curmap].selecteditemtype; 1943 changestate(S_MATCHSIZE); 1944 drawmap(TRUE); 1945 break; 1946 } 1947 } 1948 } 1949 if (c == 'g') { /* toggle snap-to-grid */ 1950 togglegrid(); 1951 drawtoolbox(); 1952 } 1953 if (c == ';') { /* change gridsize */ 1954 changegridsize(); 1955 drawmap(TRUE); 1956 } 1957 if (c == 'c') { /* copy */ 1958 copy(); 1959 } 1960 if (c == 'd') { /* drill down */ 1961 if (state == S_NONE) { 1962 if ((map[curmap].selecteditemtype == T_OBJECT) && (map[curmap].selecteditem != -1)) { 1963 drillto(map[curmap].obj[map[curmap].selecteditem].child); 1964 } else { 1965 seterror(255); 1966 sprintf(statustext,"Cannot drill down - no object selected!"); 1967 drawstatusbar(); 1968 } 1969 } else { 1970 seterror(255); 1971 sprintf(statustext,"Cannot drill down in state %d.",state); 1972 drawstatusbar(); 1973 } 1974 } 1975 if (c == 'f') { 1976 if (showflows) { 1977 showflows = FALSE; 1978 setinfo(255); 1979 sprintf(statustext, "Traffic flows hidden."); 1980 } else { 1981 setinfo(255); 1982 sprintf(statustext, "Traffic flows displayed."); 1983 showflows = TRUE; 1984 } 1985 drawtoolbox(); 1986 drawmap(TRUE); 1987 } 1988 if ((c == 'p') || (c == 'v')) { /* paste */ 1989 paste(); 1990 } 1991 /* keyboard shortcuts */ 1992 if ((c >= '0') && (c <= '9')) { 1993 int mx,my; 1994 int onum; 1995 1996 onum = c - '0'; 1997 1998 SDL_GetMouseState(&mx, &my); 1999 if (isonobox(mx, my)) { 2000 int seltype, tempx, tempy; 2001 /* define shortcut */ 2002 tempx = (mx - obox.x) / (obox.gridsize+3); 2003 tempy = (my - obox.y) / (obox.gridsize+3); 2004 seltype = tempy*obox.gridrowlen + tempx + (obox.pos*3); 2005 2006 shortcut[onum] = seltype; 2007 setinfo(255); 2008 sprintf(statustext,"Shortcut key '%c' set to '%s'.\n",c, objtype[seltype].name); 2009 drawstatusbar(); 2010 drawobox(); 2011 } else { 2012 /* select shortcut */ 2013 int fitx, fity, fit; 2014 /* select object */ 2015 map[curmap].selectedtype = shortcut[onum]; 2016 /* these two should never happen... */ 2017 if (map[curmap].selectedtype < 0 ) map[curmap].selectedtype = 0; 2018 if (map[curmap].selectedtype >= numobjtypes) map[curmap].selectedtype = numobjtypes-1; 2019 /* ensure that object is visible */ 2020 fitx = (obox.width / obox.gridsize); 2021 fity = ((obox.height+3) / obox.gridsize); 2022 fit = fitx * fity; 2023 2024 /* scroll object box to make it visible */ 2025 while (shortcut[onum] < (obox.pos*fitx)) { 2026 obox.pos--; 2027 } 2028 while (shortcut[onum] > ((obox.pos*fitx) + fit)) { 2029 obox.pos++; 2030 } 2031 2032 sprintf(statustext,"Object type shortcut #%d ('%s') selected.\n",onum, objtype[map[curmap].selectedtype].name); 2033 drawstatusbar(); 2034 drawobox(); 2035 SDL_UpdateRect(screen, obox.x, obox.y, obox.width,obox.height); 2036 } 2037 } 2038 if (c2 == SDLK_BACKSPACE) { 2039 goback(); 2040 } 2041 if (c2 == SDLK_PAGEUP) { 2042 scrollobox(-OBOXPAGESIZE); 2043 } 2044 if (c2 == SDLK_PAGEDOWN) { 2045 scrollobox(OBOXPAGESIZE); 2046 } 2047 if (c2 == SDLK_DELETE) { 2048 if (map[curmap].selecteditem != -1) { 2049 if (map[curmap].selecteditemtype == T_LINKPOINT) { 2050 int i; 2051 for (i = map[curmap].selectedlinkpoint; i < (map[curmap].olink[map[curmap].selecteditem].npoints-1); i++) { 2052 map[curmap].olink[map[curmap].selecteditem].point[i].x = map[curmap].olink[map[curmap].selecteditem].point[i+1].x; 2053 map[curmap].olink[map[curmap].selecteditem].point[i].y = map[curmap].olink[map[curmap].selecteditem].point[i+1].y; 2054 } 2055 map[curmap].olink[map[curmap].selecteditem].npoints--; 2056 2057 /* move selection to next point on same line */ 2058 if (map[curmap].olink[map[curmap].selecteditem].npoints > 0) { 2059 if (map[curmap].selectedlinkpoint >= map[curmap].olink[map[curmap].selecteditem].npoints) { 2060 map[curmap].selectedlinkpoint = map[curmap].olink[map[curmap].selecteditem].npoints-1; 2061 } 2062 } else { 2063 /* deselect point (leave link selected) */ 2064 map[curmap].selectedlinkpoint = -1; 2065 map[curmap].selecteditemtype = T_LINK; 2066 } 2067 2068 sprintf(statustext, "Deleted link #%d point #%d.",map[curmap].selecteditem,map[curmap].selectedlinkpoint); 2069 drawmap(TRUE); 2070 } else { 2071 deletething(map[curmap].selecteditem,map[curmap].selecteditemtype); 2072 } 2073 } 2074 } 2075 if (map[curmap].selecteditem != -1) { 2076 if (c == ']') { /* raise */ 2077 int amt; 2078 2079 tmod = SDL_GetModState(); 2080 if ((tmod & KMOD_SHIFT)) { 2081 amt = (map[curmap].numthings / MULTIRAISENUM); 2082 } else amt = 1; 2083 2084 /* raise the selected map[curmap].object */ 2085 raiseselected(amt); 2086 } 2087 if (c == '[') { /* lower */ 2088 int amt; 2089 2090 tmod = SDL_GetModState(); 2091 if ((tmod & KMOD_SHIFT)) { 2092 amt = (map[curmap].numthings / MULTIRAISENUM); 2093 } else amt = 1; 2094 2095 /* lower the selected map[curmap].object */ 2096 lowerselected(amt); 2097 } 2098 if (c == '{') { /* lower by lots */ 2099 int amt = (map[curmap].numthings / MULTIRAISENUM); 2100 lowerselected(amt); 2101 } 2102 if (c == '}') { /* raise by lots */ 2103 int amt = (map[curmap].numthings / MULTIRAISENUM); 2104 raiseselected(amt); 2105 } 2106 } 2107 } 2108 break; 2109 } 2110 2111 if (infoflash || errorflash) { 2112 if (!SDL_PollEvent(&event)) isevent = FALSE; 2113 } else { 2114 isevent = FALSE; 2115 } 2116 } 2117 2118 } /* end main loop */ 2119 2120 return 0; 2121 } 2122 2123 void addlinkpoint(int linkid, int x, int y) { 2124 int pos; 2125 int i; 2126 2127 pos = findpointpos(&map[curmap].olink[linkid],x,y); 2128 2129 map[curmap].olink[linkid].npoints++; 2130 2131 /* shuffle points from that point upwards */ 2132 for (i = (map[curmap].olink[linkid].npoints-1);i > pos ; i--) { 2133 map[curmap].olink[linkid].point[i] = map[curmap].olink[linkid].point[i-1]; 2134 } 2135 2136 map[curmap].olink[linkid].point[pos].x = x; 2137 map[curmap].olink[linkid].point[pos].y = y; 2138 2139 setmod(TRUE); 2140 sprintf(statustext, "Point added to link #%d at position %d,%d.",linkid, x, y); 2141 } 2142 2143 int addvector(vectorimg_t *vimg, int type, int x1, int y1, int x2, int y2, SDL_Color *c, SDL_Color *fc) { 2144 2145 if ((vimg->vnum + 1) >= MAXVECTORSPERIMAGE) return TRUE; 2146 vimg->vector[vimg->vnum].type = type; 2147 vimg->vector[vimg->vnum].x1 = x1; 2148 vimg->vector[vimg->vnum].y1 = y1; 2149 vimg->vector[vimg->vnum].x2 = x2; 2150 vimg->vector[vimg->vnum].y2 = y2; 2151 vimg->vector[vimg->vnum].c.r = c->r; 2152 vimg->vector[vimg->vnum].c.g = c->g; 2153 vimg->vector[vimg->vnum].c.b = c->b; 2154 vimg->vector[vimg->vnum].c.unused = 0; 2155 if (fc == NULL) { 2156 vimg->vector[vimg->vnum].fc.r = 0; 2157 vimg->vector[vimg->vnum].fc.g = 0; 2158 vimg->vector[vimg->vnum].fc.b = 0; 2159 vimg->vector[vimg->vnum].fc.unused = 0; 2160 } else { 2161 vimg->vector[vimg->vnum].fc.r = fc->r; 2162 vimg->vector[vimg->vnum].fc.g = fc->g; 2163 vimg->vector[vimg->vnum].fc.b = fc->b; 2164 vimg->vector[vimg->vnum].fc.unused = fc->unused; 2165 } 2166 vimg->vnum = vimg->vnum + 1; 2167 2168 return FALSE; 2169 } 2170 2171 void calcmapdimensions(void) { 2172 int thismaxx,thismaxy; /* used to calculate map size */ 2173 int maxx = -1,maxy = -1; /* used to calculate map size */ 2174 int i; 2175 2176 /* draw all map[curmap].objects links etc*/ 2177 for (i = 0; i < map[curmap].numthings; i++) { 2178 if (map[curmap].thing[i].type == T_OBJECT) { 2179 /* calculate max map size */ 2180 thismaxx = map[curmap].obj[map[curmap].thing[i].id].x + map[curmap].obj[map[curmap].thing[i].id].w; 2181 thismaxy = map[curmap].obj[map[curmap].thing[i].id].y + map[curmap].obj[map[curmap].thing[i].id].h; 2182 if (thismaxx > maxx) maxx = thismaxx; 2183 if (thismaxy > maxy) maxy = thismaxy; 2184 } else if (map[curmap].thing[i].type == T_LINK) { 2185 int p; 2186 thismaxx = -1; 2187 thismaxy = -1; 2188 for (p = 0; p < map[curmap].olink[map[curmap].thing[i].id].npoints; p++) { 2189 if (map[curmap].olink[map[curmap].thing[i].id].point[p].x > thismaxx) 2190 thismaxx = map[curmap].olink[map[curmap].thing[i].id].point[p].x; 2191 if (map[curmap].olink[map[curmap].thing[i].id].point[p].y > thismaxy) 2192 thismaxy = map[curmap].olink[map[curmap].thing[i].id].point[p].y; 2193 } 2194 /* calculate max map size */ 2195 if (thismaxx > maxx) maxx = thismaxx; 2196 if (thismaxy > maxy) maxy = thismaxy; 2197 } else if (map[curmap].thing[i].type == T_TEXT) { 2198 /* calculate max map size */ 2199 thismaxx = map[curmap].textob[map[curmap].thing[i].id].x + map[curmap].textob[map[curmap].thing[i].id].w; 2200 thismaxy = map[curmap].textob[map[curmap].thing[i].id].y + map[curmap].textob[map[curmap].thing[i].id].h; 2201 if (thismaxx > maxx) maxx = thismaxx; 2202 if (thismaxy > maxy) maxy = thismaxy; 2203 } else { 2204 printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type); 2205 } 2206 } 2207 2208 /* set map dimensions - automatically grow/shrink to be a bit bigger than required size */ 2209 if (maxx <= (map[curmap].width - 300)) map[curmap].width = maxx + 100; 2210 if (maxy <= (map[curmap].height - 300)) map[curmap].height = maxx + 100; 2211 if (maxx+200 > map[curmap].width) map[curmap].width = maxx + 200; 2212 if (maxy+200 > map[curmap].height) map[curmap].height = maxy + 200; 2213 2214 /* make sure map is always at least as big as the visible screen size */ 2215 if (map[curmap].width < screen->w - SIDEBARW) map[curmap].width = screen->w - SIDEBARW; 2216 if (map[curmap].height < screen->h - STATUSH) map[curmap].height = screen->h - STATUSH; 2217 2218 2219 2220 /* determine position of sidebar */ 2221 obox.x = screen->w - SIDEBARW; 2222 obox.y = ((screen->h / 4) * 3) - 10; 2223 obox.width = SIDEBARW; 2224 obox.height = screen->h - obox.y; 2225 obox.bgcol = black; 2226 obox.gridbgcol = grey; 2227 obox.gridcol = grey; 2228 obox.gridsize = 30; 2229 obox.gridrowlen = SIDEBARW / obox.gridsize; 2230 2231 toolbox.x = screen->w - SIDEBARW; 2232 toolbox.y = 0; 2233 toolbox.width = SIDEBARW; 2234 toolbox.height = screen->h / 3; 2235 toolbox.bgcol = black; 2236 toolbox.gridsize = 30; 2237 toolbox.gridrowlen = SIDEBARW / toolbox.gridsize; 2238 2239 mapbox.x = screen->w - SIDEBARW; 2240 mapbox.y = toolbox.y+toolbox.height+10; 2241 mapbox.width = SIDEBARW; 2242 mapbox.height = obox.y - mapbox.y - 20; 2243 mapbox.offset = 0; 2244 2245 } 2246 2247 int setgridsize(int size) { 2248 int n; 2249 for (n = 0; n < gridsizenum; n++) { 2250 if (gridsizelist[n] == size) { 2251 gridsizeindex = n; 2252 gridsize = gridsizelist[n]; 2253 return FALSE; 2254 } 2255 } 2256 2257 return TRUE; 2258 } 2259 2260 void changegridsize(void) { 2261 if (++gridsizeindex >= gridsizenum) { 2262 gridsizeindex = 0; 2263 } 2264 gridsize = gridsizelist[gridsizeindex]; 2265 setinfo(255); 2266 sprintf(statustext, "Grid size set to %d.", gridsize); 2267 } 2268 2269 void changelinearrow(int changeby) { 2270 2271 if ((changeby < 0) && (defarrow == 0)) { 2272 defarrow = AP_BOTH; 2273 } else { 2274 defarrow += changeby; 2275 } 2276 2277 /* wrap around */ 2278 if (defarrow > AP_BOTH) defarrow = 0; 2279 2280 /* change arrow style on currently selected line */ 2281 if (map[curmap].selecteditemtype == T_LINK) { 2282 if (map[curmap].selecteditem != -1) { 2283 map[curmap].olink[map[curmap].selecteditem].style &= 0x00ffff; 2284 map[curmap].olink[map[curmap].selecteditem].style |= (defarrow << 16); 2285 setmod(TRUE); 2286 drawmap(TRUE); 2287 } 2288 } 2289 2290 /* redraw toolbox */ 2291 drawtoolbox(); 2292 } 2293 2294 void changelinestyle(int changeby) { 2295 if ((changeby < 0) && (defstyle == 0)) { 2296 defstyle = MAXLINESTYLE - 1; 2297 } else { 2298 defstyle += changeby; 2299 } 2300 /* wrap around */ 2301 if (defstyle >= MAXLINESTYLE) defstyle = 0; 2302 2303 /* change line style of currently selected line */ 2304 if (map[curmap].selecteditemtype == T_LINK) { 2305 if (map[curmap].selecteditem != -1) { 2306 map[curmap].olink[map[curmap].selecteditem].style &= 0xff00ff; 2307 map[curmap].olink[map[curmap].selecteditem].style |= (defstyle << 8); 2308 setmod(TRUE); 2309 drawmap(TRUE); 2310 } 2311 } 2312 2313 /* redraw toolbox */ 2314 drawtoolbox(); 2315 } 2316 2317 void changelinethickness(int changeby) { 2318 defthickness += changeby; 2319 /* wrap around */ 2320 if (defthickness <= 0) defthickness = 5; 2321 if (defthickness > 5) defthickness = 1; 2322 2323 /* change thickness of currently selected line */ 2324 if (map[curmap].selecteditemtype == T_LINK) { 2325 if (map[curmap].selecteditem != -1) { 2326 map[curmap].olink[map[curmap].selecteditem].style &= 0xffff00; 2327 map[curmap].olink[map[curmap].selecteditem].style |= defthickness; 2328 setmod(TRUE); 2329 drawmap(TRUE); 2330 } 2331 } 2332 2333 /* redraw toolbox */ 2334 drawtoolbox(); 2335 } 2336 2337 void changemap(int newmap) { 2338 map[newmap].selecteditem = -1; 2339 map[newmap].selecteditemtype = -1; 2340 /*map[newmap].selectedtype = map[curmap].selectedtype; */ 2341 curmap = newmap; 2342 } 2343 2344 void changestate(int newstate) { 2345 int oldstate; 2346 2347 oldstate = state; 2348 /* can't do most things in readonly mode */ 2349 if (readonly) { 2350 switch (newstate) { 2351 case S_NONE: 2352 case S_LOADING: 2353 case S_REALLYQUIT: 2354 break; 2355 default: 2356 newstate = S_NONE; 2357 break; 2358 } 2359 } 2360 if (newstate != state) { 2361 if (oldstate == S_DRAWFLOW) { 2362 showflows = oldshowflows; 2363 } 2364 if ((state == S_ADDOBJ) || (state == S_ADDTEXT)) { 2365 /* change mouse back to normal */ 2366 SDL_SetCursor(normalmouse); 2367 } 2368 if (newstate == S_ADDOBJ) SDL_SetCursor(objmouse); 2369 if (newstate == S_ADDTEXT) SDL_SetCursor(textmouse); 2370 2371 state = newstate; 2372 if (oldstate == S_DRAWFLOW) { 2373 drawmap(TRUE); 2374 } 2375 drawtoolbox(); 2376 switch (state) { 2377 case S_NONE: 2378 //sprintf(statustext,"Selection mode enabled.\n"); fflush(STDOUT); 2379 if (oldstate == S_DRAWFLOW) { 2380 sprintf(statustext,"Traffic flow definition complete."); 2381 } 2382 break; 2383 case S_ADDOBJ: 2384 sprintf(statustext,"Object creation mode enabled.\n"); 2385 break; 2386 case S_CHANGEOBJECT: 2387 setinfo(255); 2388 sprintf(statustext,"Object type modification mode enabled - select new object type...\n"); 2389 break; 2390 case S_ADDTEXT: 2391 sprintf(statustext,"Text creation mode entered.\n"); 2392 break; 2393 case S_TYPETEXT: 2394 sprintf(statustext,"Text entry mode entered.\n"); 2395 break; 2396 case S_EDITTEXT: 2397 sprintf(statustext,"Text edit mode entered.\n"); 2398 break; 2399 case S_MATCHSIZE: 2400 setinfo(255); 2401 sprintf(statustext,"Size-matching mode entered - select object to copy size from...\n"); 2402 break; 2403 case S_MATCHX: 2404 setinfo(255); 2405 sprintf(statustext,"X-matching mode entered - select item to align with...\n"); 2406 break; 2407 case S_MATCHY: 2408 setinfo(255); 2409 sprintf(statustext,"Y-matching mode entered - select item to align with...\n"); 2410 break; 2411 case S_DRAWFLOW: 2412 setinfo(255); 2413 sprintf(statustext,"Traffic flow definition mode entered - select items...\n"); 2414 break; 2415 case S_MAPNAMING: 2416 sprintf(statustext,"Map rename mode entered.\n"); 2417 break; 2418 case S_SEARCH: 2419 sprintf(statustext,"Search mode entered.\n"); 2420 break; 2421 case S_SAVING: 2422 sprintf(statustext,"Save mode entered.\n"); 2423 break; 2424 case S_LOADING: 2425 sprintf(statustext,"Load mode entered.\n"); 2426 break; 2427 case S_XSCROLL: 2428 sprintf(statustext,"Scrolling horizontally...\n"); 2429 break; 2430 case S_YSCROLL: 2431 sprintf(statustext,"Scrolling vertically...\n"); 2432 break; 2433 } 2434 drawstatusbar(); 2435 } 2436 } 2437 2438 void cleanup(void) { 2439 int i; 2440 SDL_FreeCursor(textmouse); 2441 SDL_FreeCursor(objmouse); 2442 for (i = 1; i < MAXLETTERHEIGHT; i++) { 2443 TTF_CloseFont(font[i]); 2444 } 2445 TTF_Quit(); 2446 SDL_EnableUNICODE(0); 2447 SDL_Quit(); 2448 } 2449 2450 void copy(void) { 2451 if (map[curmap].selecteditem == -1) { 2452 /* copy entire map */ 2453 copytype = T_MAP; 2454 copyfrom = -1; 2455 copymap = curmap; 2456 sprintf(statustext,"Map %d ('%s') set as copy source.",curmap, map[curmap].name); 2457 drawstatusbar(); 2458 } else { 2459 if (map[curmap].selecteditemtype == T_OBJECT) { 2460 copytype = T_OBJECT; 2461 copymap = curmap; 2462 copyfrom = map[curmap].selecteditem; 2463 sprintf(statustext,"Object %d set as copy source.",copyfrom); 2464 drawstatusbar(); 2465 } else if (map[curmap].selecteditemtype == T_TEXT) { 2466 copytype = T_TEXT; 2467 copymap = curmap; 2468 copyfrom = map[curmap].selecteditem; 2469 sprintf(statustext,"Text %d ('%s') set as copy source.",copyfrom, map[curmap].textob[copyfrom].text); 2470 drawstatusbar(); 2471 } 2472 } 2473 } 2474 2475 int createobject(int type, int x, int y) { 2476 map[curmap].obj[map[curmap].numobjects].type = type; 2477 map[curmap].obj[map[curmap].numobjects].w = objtype[type].defw; 2478 map[curmap].obj[map[curmap].numobjects].h = objtype[type].defh; 2479 if ((x + map[curmap].obj[map[curmap].numobjects].w) >= map[curmap].width) { 2480 x = map[curmap].width - map[curmap].obj[map[curmap].numobjects].w - 1; 2481 } 2482 if ((y + map[curmap].obj[map[curmap].numobjects].h) >= map[curmap].height) { 2483 y = map[curmap].height - map[curmap].obj[map[curmap].numobjects].h - 1; 2484 } 2485 2486 /* adjust for grid */ 2487 if (grid) { 2488 x = x - (x % gridsize); 2489 y = y - (y % gridsize); 2490 } 2491 2492 map[curmap].obj[map[curmap].numobjects].x = x; 2493 map[curmap].obj[map[curmap].numobjects].y = y; 2494 2495 map[curmap].obj[map[curmap].numobjects].child = -1; 2496 map[curmap].obj[map[curmap].numobjects].fillcol.unused &= ~ISFLOW; /* not a flow */ 2497 2498 setmod(TRUE); 2499 sprintf(statustext,"Object #%d (%s) created at (%d,%d).\n",map[curmap].numobjects, objtype[type].name, x, y); 2500 drawstatusbar(); 2501 2502 2503 /* add to 'thing' list */ 2504 map[curmap].thing[map[curmap].numthings].type = T_OBJECT; 2505 map[curmap].thing[map[curmap].numthings].id = map[curmap].numobjects; 2506 2507 map[curmap].numobjects++; 2508 map[curmap].numthings++; 2509 2510 2511 return 0; 2512 } 2513 2514 void copyline(SDL_Surface *screen,int x1, int y1, int x2, int y2, int *lbuf) { 2515 int deltax, deltay; 2516 int numpixels; 2517 int d; 2518 int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; 2519 int i; 2520 int x; 2521 int y; 2522 SDL_Color bgcol; 2523 2524 /* store coords */ 2525 lbuf[0] = x1; 2526 lbuf[1] = y1; 2527 lbuf[2] = x2; 2528 lbuf[3] = y2; 2529 2530 deltax = (x2 - x1); 2531 if (deltax < 0) deltax = -deltax; 2532 deltay = (y2 - y1); 2533 if (deltay < 0) deltay = -deltay; 2534 2535 if (deltax >= deltay) { 2536 numpixels = deltax + 1; 2537 d = (deltay*2) - deltax; 2538 dinc1 = deltay << 1; 2539 dinc2 = (deltay-deltax) << 1; 2540 xinc1 = 1; 2541 xinc2 = 1; 2542 yinc1 = 0; 2543 yinc2 = 1; 2544 } else { 2545 numpixels = deltay + 1; 2546 d = (deltax*2) - deltay; 2547 dinc1 = deltax << 1; 2548 dinc2 = (deltax - deltay) << 1; 2549 xinc1 = 0; 2550 xinc2 = 1; 2551 yinc1 = 1; 2552 yinc2 = 1; 2553 } 2554 2555 if (x1 > x2) { 2556 xinc1 = - xinc1; 2557 xinc2 = - xinc2; 2558 } 2559 if (y1 > y2) { 2560 yinc1 = - yinc1; 2561 yinc2 = - yinc2; 2562 } 2563 2564 x = x1; y = y1; 2565 2566 for (i = 0; i < numpixels; i++) { 2567 getcolor(screen, x, y, &bgcol); 2568 lbuf[i+4] = SDL_MapRGB(screen->format, bgcol.r, bgcol.g, bgcol.b); 2569 2570 if (d < 0) { 2571 d += dinc1; 2572 x += xinc1; 2573 y += yinc1; 2574 } else { 2575 d += dinc2; 2576 x += xinc2; 2577 y += yinc2; 2578 } 2579 } 2580 2581 } 2582 2583 void deletething(int id, int type) { 2584 int i; 2585 int found; 2586 2587 2588 if (type == T_LINK) { 2589 /* remove the link*/ 2590 deletelink(id); 2591 } else if (type == T_TEXT) { 2592 deletetext(id); 2593 } else if (type == T_OBJECT) { 2594 /* remove any links connecting to this map[curmap].object */ 2595 found = 0; 2596 while (found >= 0 ) { 2597 found = -1; 2598 for (i = 0; i < map[curmap].numlinks; i++) { 2599 if ((map[curmap].olink[i].srcobj == id) || (map[curmap].olink[i].dstobj == id)) { 2600 found = i; 2601 break; 2602 } 2603 } 2604 if (found >= 0) { 2605 deletelink(found); 2606 } 2607 } 2608 2609 /* remove any text anchored to this map[curmap].object */ 2610 found = 0; 2611 while (found >= 0 ) { 2612 found = -1; 2613 for (i = 0; i < map[curmap].numtext; i++) { 2614 if (map[curmap].textob[i].anchor == id) { 2615 found = i; 2616 break; 2617 } 2618 } 2619 if (found >= 0) { 2620 deletetext(found); 2621 } 2622 } 2623 /* remove the map[curmap].object */ 2624 deleteobject(id); 2625 /* shuffle ids on any link referencing this object */ 2626 for (i = 0; i < map[curmap].numlinks; i++) { 2627 if (map[curmap].olink[i].srcobj > id) { 2628 map[curmap].olink[i].srcobj--; 2629 } 2630 if (map[curmap].olink[i].dstobj > id) { 2631 map[curmap].olink[i].dstobj--; 2632 } 2633 } 2634 /* shuffle ids on any text referencing this object */ 2635 for (i = 0; i < map[curmap].numtext; i++) { 2636 if (map[curmap].textob[i].anchor > id) { 2637 map[curmap].textob[i].anchor--; 2638 } 2639 } 2640 } 2641 setmod(TRUE); 2642 map[curmap].selecteditem = -1; 2643 map[curmap].selecteditemtype = -1; 2644 drawmap(TRUE); 2645 } 2646 2647 void deletelink(int linkid) { 2648 int i; 2649 int n; 2650 int found; 2651 2652 2653 for (i = linkid; i < (map[curmap].numlinks-1); i++) { 2654 map[curmap].olink[i] = map[curmap].olink[i+1]; 2655 } 2656 map[curmap].numlinks--; 2657 /* shuffle thing # */ 2658 for (n = 0; n < map[curmap].numthings; n++) { 2659 /* mark for deletion */ 2660 if ((map[curmap].thing[n].id == linkid) && (map[curmap].thing[n].type == T_LINK)) { 2661 map[curmap].thing[n].id = -1; 2662 } 2663 /* shuffle id */ 2664 if ((map[curmap].thing[n].id > linkid) && (map[curmap].thing[n].type == T_LINK)) { 2665 map[curmap].thing[n].id--; 2666 } 2667 } 2668 2669 found = -1; 2670 for (n = 0; n < map[curmap].numthings; n++) { 2671 if ((map[curmap].thing[n].type == T_LINK) && (map[curmap].thing[n].id == -1)) { 2672 found = n; 2673 } 2674 } 2675 2676 if (found != -1) { 2677 // remove the thing 2678 for (n = found; n < (map[curmap].numthings-1); n++) { 2679 map[curmap].thing[n] = map[curmap].thing[n+1]; 2680 } 2681 map[curmap].numthings--; 2682 } else { 2683 seterror(255); 2684 sprintf(statustext,"Can't find matching thing for link #%d!\n",linkid); 2685 } 2686 2687 setmod(TRUE); 2688 sprintf(statustext,"Deleted link #%d.\n",linkid); 2689 drawstatusbar(); 2690 2691 } 2692 2693 2694 void deleteobject(int oid) { 2695 int i; 2696 int n; 2697 int found; 2698 2699 for (i = oid; i < (map[curmap].numobjects-1); i++) { 2700 map[curmap].obj[i] = map[curmap].obj[i+1]; 2701 } 2702 map[curmap].numobjects--; 2703 /* shuffle thing # */ 2704 for (n = 0; n < map[curmap].numthings; n++) { 2705 if ((map[curmap].thing[n].id == oid) && (map[curmap].thing[n].type == T_OBJECT)) { 2706 map[curmap].thing[n].id = -1; 2707 } 2708 if ((map[curmap].thing[n].id > oid) && (map[curmap].thing[n].type == T_OBJECT)) { 2709 map[curmap].thing[n].id--; 2710 } 2711 } 2712 2713 found = -1; 2714 for (n = 0; n < map[curmap].numthings; n++) { 2715 if ((map[curmap].thing[n].type == T_OBJECT) && (map[curmap].thing[n].id == -1 )) { 2716 found = n; 2717 } 2718 } 2719 2720 if (found != -1) { 2721 // remove the thing 2722 for (n = found; n < (map[curmap].numthings-1); n++) { 2723 map[curmap].thing[n] = map[curmap].thing[n+1]; 2724 } 2725 map[curmap].numthings--; 2726 } else { 2727 seterror(255); 2728 sprintf(statustext,"Can't find matching thing for object #%d!\n",oid); 2729 } 2730 2731 setmod(TRUE); 2732 sprintf(statustext,"Deleted object #%d.\n",oid); 2733 drawstatusbar(); 2734 2735 2736 } 2737 2738 void deletetext(int textid) { 2739 int i; 2740 int n; 2741 int found; 2742 2743 2744 for (i = textid; i < (map[curmap].numtext-1); i++) { 2745 map[curmap].textob[i] = map[curmap].textob[i+1]; 2746 } 2747 map[curmap].numtext--; 2748 /* shuffle thing # */ 2749 for (n = 0; n < map[curmap].numthings; n++) { 2750 /* mark for deletion */ 2751 if ((map[curmap].thing[n].id == textid) && (map[curmap].thing[n].type == T_TEXT)) { 2752 map[curmap].thing[n].id = -1; 2753 } 2754 /* shuffle id */ 2755 if ((map[curmap].thing[n].id > textid) && (map[curmap].thing[n].type == T_TEXT)) { 2756 map[curmap].thing[n].id--; 2757 } 2758 } 2759 2760 found = -1; 2761 for (n = 0; n < map[curmap].numthings; n++) { 2762 if ((map[curmap].thing[n].type == T_TEXT) && (map[curmap].thing[n].id == -1)) { 2763 found = n; 2764 } 2765 } 2766 2767 if (found != -1) { 2768 // remove the thing 2769 for (n = found; n < (map[curmap].numthings-1); n++) { 2770 map[curmap].thing[n] = map[curmap].thing[n+1]; 2771 } 2772 map[curmap].numthings--; 2773 } else { 2774 seterror(255); 2775 sprintf(statustext,"Can't find matching thing for text item #%d!\n",textid); 2776 } 2777 2778 setmod(TRUE); 2779 sprintf(statustext,"Deleted text item #%d.\n",textid); 2780 drawstatusbar(); 2781 2782 } 2783 2784 2785 2786 void adjustendpoint(SDL_Surface *screen, int *adjx, int *adjy, double x1, double y1, double x2, double y2, int arrowstyle, int arrowpos ) { 2787 int middlex, middley; 2788 int deltax, deltay; 2789 int numpixels; 2790 int d; 2791 int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; 2792 int i,n; 2793 int x; 2794 int y; 2795 int tempx,tempy; 2796 int o,oldo; 2797 SDL_Surface *temps; 2798 int arrowthickness; 2799 2800 arrowthickness = (arrowstyle & 0x0000ff); 2801 2802 2803 /* calculate where the arrowpoint should go - follow the line until 2804 we're not on an object */ 2805 2806 if (arrowpos == AP_END) { 2807 /* temporarily reverse endpoints */ 2808 tempx = x1; 2809 tempy = y1; 2810 x1 = x2; 2811 y1 = y2; 2812 x2 = tempx; 2813 y2 = tempy; 2814 } 2815 2816 deltax = (x2 - x1); 2817 if (deltax < 0) deltax = -deltax; 2818 deltay = (y2 - y1); 2819 if (deltay < 0) deltay = -deltay; 2820 2821 if (deltax >= deltay) { 2822 numpixels = deltax + 1; 2823 d = (deltay*2) - deltax; 2824 dinc1 = deltay << 1; 2825 dinc2 = (deltay-deltax) << 1; 2826 xinc1 = 1; 2827 xinc2 = 1; 2828 yinc1 = 0; 2829 yinc2 = 1; 2830 } else { 2831 numpixels = deltay + 1; 2832 d = (deltax*2) - deltay; 2833 dinc1 = deltax << 1; 2834 dinc2 = (deltax - deltay) << 1; 2835 xinc1 = 0; 2836 xinc2 = 1; 2837 yinc1 = 1; 2838 yinc2 = 1; 2839 } 2840 2841 if (x1 > x2) { 2842 xinc1 = - xinc1; 2843 xinc2 = - xinc2; 2844 } 2845 if (y1 > y2) { 2846 yinc1 = - yinc1; 2847 yinc2 = - yinc2; 2848 } 2849 2850 x = x1; y = y1; 2851 2852 middlex = -1; 2853 middley = -1; 2854 2855 2856 /* 2857 temps = SDL_CreateRGBSurface(SDL_SWSURFACE,10,10, 2858 screen->format->BitsPerPixel, screen->format->Rmask, 2859 screen->format->Gmask,screen->format->Bmask, 2860 screen->format->Amask); 2861 */ 2862 2863 temps = NULL; 2864 o = -1; 2865 oldo = -99; 2866 2867 for (i = 0; i < numpixels; i++) { 2868 o = objat(x,y); 2869 if (o == -1) { 2870 middlex = x; 2871 middley = y; 2872 break; 2873 } else { 2874 int ox,oy; 2875 SDL_Color tempc; 2876 2877 if (o != oldo) { 2878 if (oldo == -99) { 2879 SDL_Rect area; 2880 int tid; 2881 2882 temps = SDL_CreateRGBSurface(SDL_SWSURFACE,map[curmap].obj[o].w+3, map[curmap].obj[o].h+3, 2883 screen->format->BitsPerPixel, screen->format->Rmask, 2884 screen->format->Gmask,screen->format->Bmask, 2885 screen->format->Amask); 2886 area.x = map[curmap].obj[o].x; 2887 area.y = map[curmap].obj[o].y; 2888 area.w = map[curmap].obj[o].w; 2889 area.h = map[curmap].obj[o].h; 2890 2891 /* have we already drawn the object? */ 2892 /* get thingid of this object */ 2893 tid = -1; 2894 for (n = 0; n < map[curmap].numthings; n++) { 2895 if ( (map[curmap].thing[n].id == o) && 2896 (map[curmap].thing[n].type == T_OBJECT) ) { 2897 tid = n; 2898 break; 2899 } 2900 } 2901 2902 /* FIXME: drawobject is too slow here!!! */ 2903 /* but we can't just blit from the screen, in case 2904 the object hasn't been drawn yet */ 2905 2906 2907 drawobject(temps, &map[curmap].obj[o], FALSE, TRUE); 2908 2909 2910 /* 2911 if (tid == -1) { 2912 drawobject(temps, &map[curmap].obj[o], FALSE); 2913 } else if (thingdrawn[tid] == FALSE) { 2914 drawobject(temps, &map[curmap].obj[o], FALSE); 2915 } else { 2916 SDL_BlitSurface(screen, &area, temps, NULL); 2917 } 2918 */ 2919 oldo = o; 2920 } else { 2921 if (temps != NULL) { 2922 SDL_FreeSurface(temps); 2923 temps = NULL; 2924 } 2925 middlex = x; 2926 middley = y; 2927 break; 2928 } 2929 } 2930 /* we can start drawing if we're on the object but on a transparent bit */ 2931 ox = x - map[curmap].obj[o].x; 2932 oy = y - map[curmap].obj[o].y; 2933 2934 getcolor(temps, ox + arrowthickness - 1, oy + arrowthickness -1, &tempc); 2935 if ( (tempc.r == map[curmap].bgcol.r) && 2936 (tempc.g == map[curmap].bgcol.g) && 2937 (tempc.b == map[curmap].bgcol.b)) { 2938 /* free temporary surface */ 2939 SDL_FreeSurface(temps); 2940 temps = NULL; 2941 2942 middlex = x; 2943 middley = y; 2944 break; 2945 } 2946 } 2947 2948 if (d < 0) { 2949 d += dinc1; 2950 x += xinc1; 2951 y += yinc1; 2952 } else { 2953 d += dinc2; 2954 x += xinc2; 2955 y += yinc2; 2956 } 2957 } 2958 2959 2960 if (temps != NULL) { 2961 SDL_FreeSurface(temps); 2962 temps = NULL; 2963 } 2964 *adjx = middlex; 2965 *adjy = middley; 2966 } 2967 2968 int dosearch(void) { 2969 int i; 2970 int m; 2971 2972 /* fill in search text */ 2973 strcpy(searchtext, text); 2974 2975 /* reset search point */ 2976 searchmap = 0; 2977 searchtob = 0; 2978 searchwrap = FALSE; 2979 2980 /* go through each text object until we find what we're looking for */ 2981 for (m = 0; m < nummaps; m++) { /* for each map */ 2982 for (i = 0; i < map[m].numtext; i++) { /* for each text object */ 2983 /* does it contain the search string? */ 2984 if (strstr(map[m].textob[i].text, searchtext)) { 2985 drillto(m); 2986 2987 map[m].selecteditemtype = T_TEXT; 2988 map[m].selecteditem = i; 2989 2990 searchmap = m; 2991 searchtob = i; 2992 return FALSE; 2993 } 2994 } 2995 } 2996 2997 return TRUE; 2998 } 2999 3000 int dosearchnext(void) { 3001 int i = -1; 3002 int firsttime = TRUE; 3003 int m; 3004 int numtextfound = 0; 3005 3006 /* go through each text object until we find what we're looking for */ 3007 for (m = searchmap; ; m++) { /* for each map */ 3008 3009 3010 if (m >= nummaps) { 3011 m = 0; 3012 searchwrap = TRUE; 3013 } 3014 3015 if ((m == searchmap) && (numtextfound == 0) && (!firsttime)) { 3016 /* no text objects exist */ 3017 return TRUE; 3018 } 3019 3020 if ((firsttime) && (m == searchmap)) { 3021 i = searchtob+1; 3022 firsttime = FALSE; 3023 } else { 3024 i = 0; 3025 } 3026 3027 3028 3029 for (; i < map[m].numtext; i++) { /* for each text object */ 3030 3031 /* back to start - not found */ 3032 if ((m == searchmap) && (i == searchtob)) { 3033 searchwrap = FALSE; 3034 return TRUE; 3035 } 3036 3037 /* does it contain the search string? */ 3038 if (strstr(map[m].textob[i].text, searchtext)) { 3039 drillto(m); 3040 map[m].selecteditemtype = T_TEXT; 3041 map[m].selecteditem = i; 3042 3043 searchmap = m; 3044 searchtob = i; 3045 searchwrap = FALSE; 3046 return FALSE; 3047 } 3048 } 3049 numtextfound += (map[m].numtext); 3050 3051 3052 } 3053 3054 return TRUE; 3055 } 3056 3057 3058 void drawarrowhead(SDL_Surface *screen, double x1, double y1, double x2, double y2, SDL_Color c, int arrowstyle, int arrowpos) { 3059 double angle; 3060 int arrowpointx,arrowpointy; 3061 int arrowend1x,arrowend1y; 3062 int arrowend2x,arrowend2y; 3063 int middlex, middley; 3064 int arrowlength = 5; 3065 int arrowthickness; 3066 3067 arrowthickness = (arrowstyle & 0x0000ff); 3068 3069 /* calculate arrow length based on line length 3070 line length > 40 means arrow length is 5, 3071 otherwise it's 3 */ 3072 //if (numpixels > 40) { 3073 // arrowlength = 5; 3074 //} else { 3075 arrowlength = 3; 3076 //} 3077 /* adjust for line thickness */ 3078 arrowlength = arrowlength + arrowthickness - 1; 3079 3080 /* calculate angle of line */ 3081 angle = atan2(y2-y1,x2-x1); 3082 3083 if (arrowpos == AP_START) { 3084 middlex = x1; 3085 middley = y1; 3086 } else { 3087 middlex = x2; 3088 middley = y2; 3089 } 3090 3091 if (arrowpos == AP_END) { 3092 angle += M_PI; 3093 //if (angle > 360) angle -= 360; 3094 } 3095 angle = -angle; 3096 3097 /* original arrowhead is: 3098 * 3099 * / (5,-5) 3100 * / 3101 * (0,0) < 3102 * \ 3103 * \ (5,5) 3104 */ 3105 3106 /* rotate arrowhead */ 3107 arrowpointx = 0; 3108 arrowpointy = 0; 3109 arrowend1x = (arrowlength * cos(angle)) + (-arrowlength * sin(angle)); 3110 arrowend1y = (-arrowlength * sin(angle)) + (-arrowlength * cos(angle)); 3111 arrowend2x = (arrowlength * cos(angle)) + (arrowlength * sin(angle)); 3112 arrowend2y = (-arrowlength * sin(angle)) + (arrowlength * cos(angle)); 3113 3114 3115 /* translate arrowhead into position */ 3116 arrowpointx = middlex; 3117 arrowpointy = middley; 3118 arrowend1x += middlex; 3119 arrowend1y += middley; 3120 arrowend2x += middlex; 3121 arrowend2y += middley; 3122 3123 /* get rid of the 'linestyle' and 'arrow' parts of arrowstyle to 3124 * (respectively) make sure the arrow looks okay and 3125 * avoid an infinite loop! */ 3126 arrowstyle &= 0x0000ff; 3127 3128 drawline(screen, arrowpointx, arrowpointy, arrowend1x, arrowend1y, c, arrowstyle); 3129 drawline(screen, arrowpointx, arrowpointy, arrowend2x, arrowend2y, c, arrowstyle); 3130 } 3131 3132 void drawarrowheadSVG(double x1, double y1, double x2, double y2, SDL_Color c, int arrowstyle, int arrowpos) { 3133 double angle; 3134 int arrowpointx,arrowpointy; 3135 int arrowend1x,arrowend1y; 3136 int arrowend2x,arrowend2y; 3137 int middlex, middley; 3138 int arrowlength = 5; 3139 int arrowthickness; 3140 3141 arrowthickness = (arrowstyle & 0x0000ff); 3142 3143 3144 //if (numpixels > 40) { 3145 // arrowlength = 5; 3146 //} else { 3147 arrowlength = 3; 3148 //} 3149 /* adjust for line thickness */ 3150 arrowlength = arrowlength + arrowthickness - 1; 3151 3152 /* calculate angle of line */ 3153 angle = atan2(y2-y1,x2-x1); 3154 3155 if (arrowpos == AP_START) { 3156 middlex = x1; 3157 middley = y1; 3158 } else { 3159 middlex = x2; 3160 middley = y2; 3161 } 3162 3163 3164 if (arrowpos == AP_END) { 3165 angle += M_PI; 3166 //if (angle > 360) angle -= 360; 3167 } 3168 angle = -angle; 3169 3170 /* original arrowhead is: 3171 * 3172 * / (5,-5) 3173 * / 3174 * (0,0) < 3175 * \ 3176 * \ (5,5) 3177 */ 3178 3179 /* rotate arrowhead */ 3180 arrowpointx = 0; 3181 arrowpointy = 0; 3182 arrowend1x = (arrowlength * cos(angle)) + (-arrowlength * sin(angle)); 3183 arrowend1y = (-arrowlength * sin(angle)) + (-arrowlength * cos(angle)); 3184 arrowend2x = (arrowlength * cos(angle)) + (arrowlength * sin(angle)); 3185 arrowend2y = (-arrowlength * sin(angle)) + (arrowlength * cos(angle)); 3186 3187 3188 /* translate arrowhead into position */ 3189 arrowpointx = middlex; 3190 arrowpointy = middley; 3191 arrowend1x += middlex; 3192 arrowend1y += middley; 3193 arrowend2x += middlex; 3194 arrowend2y += middley; 3195 3196 /* get rid of the 'linestyle' and 'arrow' parts of arrowstyle to 3197 * (respectively) make sure the arrow looks okay and 3198 * avoid an infinite loop! */ 3199 arrowstyle &= 0x000000ff; 3200 3201 sprintf(svgbuf,"<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d; \"/>\n", arrowpointx, arrowpointy, arrowend1x, arrowend1y,c.r,c.g,c.b, arrowstyle ); 3202 fprintf(svgfile, svgbuf); 3203 sprintf(svgbuf,"<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d; \"/>\n", arrowpointx, arrowpointy, arrowend2x, arrowend2y,c.r,c.g,c.b, arrowstyle ); 3204 fprintf(svgfile, svgbuf); 3205 } 3206 3207 void lerp(int *newx, int *newy, int ax, int ay, int bx, int by, float t) { 3208 *newx = ax + (bx - ax) * t; 3209 *newy = ay + (by - ay) * t; 3210 } 3211 3212 void drawbezier(SDL_Surface *screen, int x1, int y1, 3213 int x2,int y2, 3214 int x3,int y3, 3215 int x4,int y4, 3216 SDL_Color c) { 3217 int i; 3218 float t; 3219 int abx,aby,bcx,bcy,cdx,cdy; 3220 int abbcx,abbcy,bccdx,bccdy; 3221 int newx,newy; 3222 int oldx,oldy; 3223 3224 oldx = x1; 3225 oldy = y1; 3226 3227 for (i = 0; i < BEZIERQUALITY; i++) { 3228 t = (float)i / (float)(BEZIERQUALITY - 1); 3229 3230 lerp(&abx,&aby, x1, y1, x2, y2, t); 3231 lerp(&bcx,&bcy, x2, y2, x3, y3, t); 3232 lerp(&cdx,&cdy, x3, y3, x4, y4, t); 3233 lerp(&abbcx,&abbcy, abx, aby, bcx, bcy, t); 3234 lerp(&bccdx,&bccdy, bcx, bcy, cdx, cdy, t); 3235 lerp(&newx,&newy, abbcx, abbcy, bccdx, bccdy, t); 3236 3237 drawline(screen, oldx, oldy, newx, newy, c, 1); 3238 oldx = newx; 3239 oldy = newy; 3240 } 3241 3242 } 3243 3244 3245 void drawbox(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c, SDL_Color *fc) { 3246 if (fc != NULL) { 3247 if (fc->unused & USECOLOUR) { 3248 /* fill */ 3249 if (((x2 - x1) >= 2) && ((y2 - y1) >= 2)) { 3250 int y; 3251 for (y = (y1+1) ; y <= (y2-1); y++) { 3252 drawline(screen, x1+1, y, x2-1,y,*fc,1); 3253 } 3254 } 3255 } 3256 } 3257 drawline(screen,x1,y1,x2,y1,c,1); 3258 drawline(screen,x1,y1,x1,y2,c,1); 3259 drawline(screen,x1,y2,x2,y2,c,1); 3260 drawline(screen,x2,y1,x2,y2,c,1); 3261 } 3262 3263 void drawellipsepoints(SDL_Surface *screen, int x1, int y1, int x, int y, SDL_Color c) { 3264 drawpixel(screen, x1 + x, y1 + y, c); 3265 drawpixel(screen, x1 - x, y1 + y, c); 3266 drawpixel(screen, x1 - x, y1 - y, c); 3267 drawpixel(screen, x1 + x, y1 - y, c); 3268 } 3269 3270 void drawellipse(SDL_Surface *screen, int x1, int y1, int xr, int yr, SDL_Color c) { 3271 double x,y; 3272 double xc,yc; 3273 double ee; 3274 double twoas, twobs; 3275 double stoppingx,stoppingy; 3276 3277 twoas = 2 * xr * xr; 3278 twobs = 2 * yr * yr; 3279 3280 /* first set */ 3281 x = xr; 3282 y = 0; 3283 xc = yr * yr * (1 - 2*xr); 3284 yc = xr * xr; 3285 ee = 0; 3286 stoppingx = twobs * xr; 3287 stoppingy = 0; 3288 while (stoppingx >= stoppingy) { 3289 drawellipsepoints(screen, x1, y1, x,y, c); 3290 y++; 3291 stoppingy += twoas; 3292 ee += yc; 3293 yc += twoas; 3294 if ((2*ee + xc) > 0) { 3295 x--; 3296 stoppingx -= twobs; 3297 ee += xc; 3298 xc += twobs; 3299 } 3300 } 3301 3302 3303 /* second set */ 3304 x = 0; 3305 y = yr; 3306 xc = yr * yr; 3307 yc = xr * xr * (1 - 2*yr); 3308 ee = 0; 3309 stoppingx = 0; 3310 stoppingy = twoas * yr; 3311 while (stoppingx <= stoppingy) { 3312 drawellipsepoints(screen, x1, y1, x,y, c); 3313 x++; 3314 stoppingx += twobs; 3315 ee += xc; 3316 xc += twobs; 3317 if ((2*ee + yc) > 0) { 3318 y--; 3319 stoppingy -= twoas; 3320 ee += yc; 3321 yc += twoas; 3322 } 3323 } 3324 3325 } 3326 3327 void drawflowbox(SDL_Surface *dest, int oid, int otype) { 3328 int x1,y1,x2,y2; 3329 int i; 3330 int ls = 10; 3331 3332 switch (otype) { 3333 case T_OBJECT: 3334 x1 = map[curmap].obj[oid].x; 3335 y1 = map[curmap].obj[oid].y; 3336 x2 = map[curmap].obj[oid].x + map[curmap].obj[oid].w; 3337 y2 = map[curmap].obj[oid].y + map[curmap].obj[oid].h; 3338 drawbox(dest, x1, y1, x2, y2, blue, NULL); 3339 break; 3340 case T_LINK: 3341 x1 = map[curmap].obj[map[curmap].olink[oid].srcobj].x + map[curmap].olink[oid].srcxoff; 3342 y1 = map[curmap].obj[map[curmap].olink[oid].srcobj].y + map[curmap].olink[oid].srcyoff; 3343 x2 = map[curmap].obj[map[curmap].olink[oid].dstobj].x + map[curmap].olink[oid].dstxoff; 3344 y2 = map[curmap].obj[map[curmap].olink[oid].dstobj].y + map[curmap].olink[oid].dstyoff; 3345 drawbox(dest, x1-ls, y1-ls, x1+ls, y1+ls, blue, &blue); 3346 drawbox(dest, x2-ls, y2-ls, x2+ls, y2+ls, blue, &blue); 3347 for (i = 0; i < map[curmap].olink[oid].npoints; i++) { 3348 x1 = map[curmap].olink[oid].point[i].x; 3349 y1 = map[curmap].olink[oid].point[i].y; 3350 drawbox(dest, x1-ls, y1-ls, x1+ls, y1+ls, blue, &blue); 3351 } 3352 break; 3353 case T_TEXT: 3354 if (map[curmap].textob[oid].anchor == -1) { 3355 x1 = map[curmap].textob[oid].x; 3356 y1 = map[curmap].textob[oid].y; 3357 } else { 3358 x1 = map[curmap].textob[oid].x + map[curmap].obj[map[curmap].textob[oid].anchor].x; 3359 y1 = map[curmap].textob[oid].y + map[curmap].obj[map[curmap].textob[oid].anchor].y; 3360 } 3361 x2 = x1 + map[curmap].textob[oid].w; 3362 y2 = y1 + map[curmap].textob[oid].h; 3363 drawbox(dest, x1, y1, x2, y2, blue, NULL); 3364 break; 3365 default: 3366 return; 3367 } 3368 } 3369 3370 void drawcolorchart(SDL_Surface *dest) { 3371 int x,y; 3372 //int i; 3373 SDL_Color c; 3374 int speed; 3375 int finished = FALSE; 3376 int size = 18; 3377 3378 3379 int mode = 1; 3380 3381 c.r = 0; 3382 c.g = 0; 3383 c.b = 0; 3384 c.unused = USECOLOUR; 3385 3386 speed = 24 ; 3387 3388 for (y = 0; (y < (map[curmap].height-size)) && (!finished); y+= size) { 3389 for (x = 0; (x < (map[curmap].width-size)) && (!finished); x+= size) { 3390 drawbox(dest,x,y,x+(size-1),y+(size-1),black, &c); 3391 /* fill box */ 3392 /*for (i = 1; i <= (size-2); i++) { 3393 drawline(dest, x+1, y+i, x+(size-2), y+i, c,1); 3394 }*/ 3395 /* change color */ 3396 3397 if (mode == 1) { 3398 if (c.b + speed > 255) { 3399 c.b = 0; 3400 if (c.g + speed > 255) { 3401 c.g = 0; 3402 if (c.r + speed > 255) { 3403 c.r = 255 - speed; 3404 c.g = 255 - speed; 3405 c.b = 255 - speed; 3406 mode = 2; 3407 } else c.r += speed; 3408 } else c.g += speed; 3409 } else c.b += speed; 3410 } else { 3411 if (c.r-speed <= 0) finished = TRUE; 3412 if (c.g-speed <= 0) finished = TRUE; 3413 if (c.b-speed <= 0) finished = TRUE; 3414 c.r -= speed; 3415 c.g -= speed; 3416 c.b -= speed; 3417 } 3418 3419 if (c.r >= 240) c.r = 255; 3420 if (c.g >= 240) c.g = 255; 3421 if (c.b >= 240) c.b = 255; 3422 } 3423 } 3424 SDL_Flip(screen); 3425 } 3426 3427 int findpointpos(link_t *l, int px, int py) { 3428 int i; 3429 int x,y,x2,y2; 3430 int pos = 0; 3431 3432 x = map[curmap].obj[l->srcobj].x + l->srcxoff; 3433 y = map[curmap].obj[l->srcobj].y + l->srcyoff; 3434 3435 for (i = 0; i < l->npoints; i++) { 3436 x2 = l->point[i].x; 3437 y2 = l->point[i].y; 3438 3439 if (isonline(px, py, x, y, x2, y2)) { 3440 return pos; 3441 } 3442 pos++; 3443 3444 x = x2; 3445 y = y2; 3446 } 3447 3448 /* draw line to final map[curmap].object */ 3449 x2 = map[curmap].obj[l->dstobj].x + l->dstxoff; 3450 y2 = map[curmap].obj[l->dstobj].y + l->dstyoff; 3451 3452 return pos; 3453 } 3454 3455 void drawline(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c, int linestyle) { 3456 int deltax, deltay; 3457 int numpixels; 3458 int d; 3459 int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; 3460 int i; 3461 int x; 3462 int y; 3463 int xx,yy; 3464 int maskcount = 0; 3465 int maskindex = 0; 3466 Uint8 arrow,style, thickness; 3467 3468 arrow = (linestyle & (0x00ff0000)) >> 16; 3469 style = (linestyle & (0x0000ff00)) >> 8; 3470 thickness = (linestyle & (0x000000ff)); 3471 3472 3473 deltax = (x2 - x1); 3474 if (deltax < 0) deltax = -deltax; 3475 deltay = (y2 - y1); 3476 if (deltay < 0) deltay = -deltay; 3477 3478 if (deltax >= deltay) { 3479 numpixels = deltax + 1; 3480 d = (deltay*2) - deltax; 3481 dinc1 = deltay << 1; 3482 dinc2 = (deltay-deltax) << 1; 3483 xinc1 = 1; 3484 xinc2 = 1; 3485 yinc1 = 0; 3486 yinc2 = 1; 3487 } else { 3488 numpixels = deltay + 1; 3489 d = (deltax*2) - deltay; 3490 dinc1 = deltax << 1; 3491 dinc2 = (deltax - deltay) << 1; 3492 xinc1 = 0; 3493 xinc2 = 1; 3494 yinc1 = 1; 3495 yinc2 = 1; 3496 } 3497 3498 if (x1 > x2) { 3499 xinc1 = - xinc1; 3500 xinc2 = - xinc2; 3501 } 3502 if (y1 > y2) { 3503 yinc1 = - yinc1; 3504 yinc2 = - yinc2; 3505 } 3506 3507 x = x1; y = y1; 3508 3509 maskcount = 0; 3510 maskindex = 0; 3511 for (i = 0; i < numpixels; i++) { 3512 3513 if (linemask[style][maskindex] == 1) { 3514 /* plot point */ 3515 for (yy = 0; yy < thickness ; yy++) { 3516 for (xx = 0; xx < thickness ; xx++) { 3517 drawpixel(screen,x+xx,y+yy,c); 3518 } 3519 } 3520 } 3521 3522 /* increment mask count */ 3523 if (++maskcount >= thickness) { 3524 maskcount = 0; 3525 /* increment mask index */ 3526 maskindex++; 3527 if (maskindex >= LINESTYLESIZE) { 3528 maskindex = 0; 3529 } 3530 if (linemask[style][maskindex] == -1) maskindex = 0; 3531 } 3532 3533 3534 if (d < 0) { 3535 d += dinc1; 3536 x += xinc1; 3537 y += yinc1; 3538 } else { 3539 d += dinc2; 3540 x += xinc2; 3541 y += yinc2; 3542 } 3543 } 3544 3545 /* draw arrowheads if required */ 3546 if (arrow) { 3547 if ((arrow == AP_START) || (arrow == AP_END)) { 3548 drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, arrow); 3549 } else if (arrow == AP_BOTH) { 3550 drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, AP_START); 3551 drawarrowhead(screen, x1, y1, x2, y2, c, linestyle, AP_END); 3552 } 3553 } 3554 } 3555 3556 3557 void drawlink(SDL_Surface *dest, link_t *l) { 3558 int i; 3559 int x,y,x2,y2; 3560 int arrow; 3561 int adjx,adjy; 3562 int flow; 3563 3564 flow = l->col.unused & ISFLOW; 3565 3566 x = map[curmap].obj[l->srcobj].x + l->srcxoff - screenx; 3567 y = map[curmap].obj[l->srcobj].y + l->srcyoff - screeny; 3568 arrow = (l->style & 0x00ff0000) >> 16; 3569 3570 for (i = 0; i < l->npoints; i++) { 3571 x2 = l->point[i].x - screenx; 3572 y2 = l->point[i].y - screeny; 3573 3574 /* if this is the first point and the line is of 3575 type "arrowhead at start" then draw an arrow */ 3576 3577 if ( (i == 0) && 3578 ((arrow == AP_START) || (arrow == AP_BOTH)) 3579 ) { 3580 int tempstyle; 3581 tempstyle = l->style & (0xff00ffff); 3582 tempstyle |= (AP_START << 16); 3583 3584 /* adjust start point */ 3585 if (flow) { 3586 adjx = x; 3587 adjy = y; 3588 } else { 3589 adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); 3590 } 3591 drawline(dest, adjx,adjy,x2,y2, l->col,tempstyle); 3592 } else { 3593 /* clear the "arrowhead" part of these */ 3594 adjx = x; 3595 adjy = y; 3596 drawline(dest, adjx,adjy,x2,y2, l->col,l->style & 0xff00ffff); 3597 } 3598 3599 x = x2; 3600 y = y2; 3601 } 3602 3603 /* draw line to final map[curmap].object */ 3604 x2 = map[curmap].obj[l->dstobj].x + l->dstxoff - screenx; 3605 y2 = map[curmap].obj[l->dstobj].y + l->dstyoff - screeny; 3606 3607 /* adjust end */ 3608 if (l->npoints >= 1) { 3609 if ( (arrow == AP_END) || (arrow == AP_BOTH)) { 3610 int tempstyle; 3611 tempstyle = l->style & (0xff00ffff); 3612 tempstyle |= (AP_END << 16); 3613 3614 if (!flow) { 3615 adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_END); 3616 x2 = adjx ; y2 = adjy; 3617 } 3618 3619 drawline(dest, x,y,x2,y2, l->col,tempstyle); 3620 } else { 3621 /* clear the "arrowhead" part of these */ 3622 drawline(dest, x,y,x2,y2, l->col,l->style & 0xff00ffff); 3623 } 3624 } else { 3625 /* adjust start */ 3626 if (!flow) { 3627 if ((arrow == AP_START) || (arrow == AP_BOTH)) { 3628 adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_START); 3629 x = adjx ; y = adjy; 3630 } 3631 } 3632 /* adjust end */ 3633 if (!flow) { 3634 if ((arrow == AP_END) || (arrow == AP_BOTH)) { 3635 adjustendpoint(dest, &adjx, &adjy, x,y,x2,y2,l->style & 0xff00ffff, AP_END); 3636 x2 = adjx ; y2 = adjy; 3637 } 3638 } 3639 drawline(dest, x,y,x2,y2, l->col,l->style); 3640 } 3641 } 3642 3643 void drawlinkSVG(link_t *l) { 3644 int i; 3645 int x,y,x2,y2; 3646 int width; 3647 char temp[BUFLEN]; 3648 char dasharray[BUFLEN]; 3649 int linestyle; 3650 int cur,old; 3651 int count; 3652 int first; 3653 int arrow; 3654 int adjx,adjy; 3655 int flow; 3656 3657 x = map[curmap].obj[l->srcobj].x + l->srcxoff; 3658 y = map[curmap].obj[l->srcobj].y + l->srcyoff; 3659 3660 flow = l->col.unused & ISFLOW; 3661 3662 /* get attributes */ 3663 width = l->style & 0x000000ff; 3664 linestyle = (l->style & 0x0000ff00) >> 8; 3665 arrow = (l->style & 0x00ff0000) >> 16; 3666 3667 old = linemask[linestyle][0]; 3668 count = 1; 3669 first = 1; 3670 3671 sprintf(dasharray, "stroke-dasharray:"); 3672 for (i = 0; linemask[linestyle][i] != -1; i++) { 3673 cur = linemask[linestyle][i]; 3674 //sprintf(temp, "[%d]", cur); 3675 //strcat(dasharray, temp); 3676 if (cur == old) { 3677 count++; 3678 } else { 3679 if (first) { 3680 sprintf(temp, "%d", count*width); 3681 first = 0; 3682 } else { 3683 sprintf(temp, ",%d", count*width); 3684 } 3685 count = 1; 3686 strcat(dasharray, temp); 3687 old = cur; 3688 } 3689 } 3690 3691 if (first == 1) { 3692 /* don't need dash-array */ 3693 strcpy(dasharray, ""); 3694 } else { 3695 sprintf(temp, ",%d", count*width); 3696 strcat(dasharray, temp); 3697 } 3698 3699 3700 for (i = 0; i < l->npoints; i++) { 3701 x2 = l->point[i].x; 3702 y2 = l->point[i].y; 3703 3704 3705 sprintf(svgbuf,"<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d; %s;\"/>\n", x, y, x2, y2,l->col.r,l->col.g,l->col.b, width ,dasharray); 3706 fprintf(svgfile, svgbuf); 3707 3708 /* draw arrowhead if required */ 3709 if ( (i == 0) && 3710 ((arrow == AP_START) || (arrow == AP_BOTH)) 3711 ) { 3712 int tempstyle; 3713 tempstyle = l->style & (0xff00ffff); 3714 tempstyle |= (AP_START << 16); 3715 3716 if (flow) { 3717 adjx = x; 3718 adjy = y; 3719 } else { 3720 adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); 3721 } 3722 3723 drawarrowheadSVG(adjx,adjy,x2,y2, l->col,tempstyle, arrow); 3724 } 3725 3726 x = x2; 3727 y = y2; 3728 } 3729 3730 /* draw line to final map[curmap].object */ 3731 x2 = map[curmap].obj[l->dstobj].x + l->dstxoff; 3732 y2 = map[curmap].obj[l->dstobj].y + l->dstyoff; 3733 3734 /* draw arrow if required */ 3735 if (l->npoints >= 1) { 3736 if ( (arrow == AP_END) || (arrow == AP_BOTH)) { 3737 int tempstyle; 3738 tempstyle = l->style & (0xff00ffff); 3739 tempstyle |= (AP_END << 16); 3740 3741 if (!flow) { 3742 adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_END); 3743 x2 = adjx; 3744 y2 = adjy; 3745 } 3746 drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_END); 3747 } 3748 } else { 3749 /* adjust start point too */ 3750 3751 if ( (arrow == AP_START) || (arrow == AP_BOTH)) { 3752 int tempstyle; 3753 tempstyle = l->style & (0xff00ffff); 3754 tempstyle |= (AP_START << 16); 3755 3756 if (!flow) { 3757 adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_START); 3758 x = adjx; 3759 y = adjy; 3760 } 3761 3762 drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_START); 3763 } 3764 if ( (arrow == AP_END) || (arrow == AP_BOTH)) { 3765 int tempstyle; 3766 tempstyle = l->style & (0xff00ffff); 3767 tempstyle |= (AP_END << 16); 3768 3769 if (!flow) { 3770 adjustendpoint(screen, &adjx, &adjy, x,y,x2,y2,l->style, AP_END); 3771 x2 = adjx; 3772 y2 = adjy; 3773 } 3774 3775 drawarrowheadSVG(x,y,x2,y2, l->col,tempstyle, AP_END); 3776 } 3777 } 3778 3779 3780 3781 sprintf(svgbuf,"<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d; %s;\"/>\n", x, y, x2, y2,l->col.r,l->col.g,l->col.b, width ,dasharray); 3782 fprintf(svgfile, svgbuf); 3783 } 3784 3785 3786 void drawobject(SDL_Surface *dest, mapobject_t *o, int doublebuffer, int adjust) { 3787 SDL_Surface *temps; 3788 SDL_Rect area; 3789 Uint32 bgcol; 3790 int testing = 0; 3791 3792 /* create temp surface */ 3793 if (testing) { 3794 printf("About to create surface..."); 3795 fflush(STDOUT); 3796 } 3797 if (doublebuffer) { 3798 temps = SDL_CreateRGBSurface(SDL_SWSURFACE,o->w+3, o->h+3, 3799 screen->format->BitsPerPixel, screen->format->Rmask, 3800 screen->format->Gmask,screen->format->Bmask, 3801 screen->format->Amask); 3802 } else { 3803 temps = dest; 3804 } 3805 3806 bgcol = SDL_MapRGB(temps->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b); 3807 SDL_FillRect(temps, NULL, bgcol); 3808 3809 /* draw onto temp surface */ 3810 if (testing) { 3811 printf("About to drawvector ..."); 3812 fflush(STDOUT); 3813 } 3814 if (o->fillcol.unused & USECOLOUR) { 3815 drawvector(temps, &objtype[o->type].vimg, 0, 0, o->w, o->h, NULL, &o->fillcol); 3816 } else { 3817 drawvector(temps, &objtype[o->type].vimg, 0, 0, o->w, o->h, NULL, NULL); 3818 } 3819 3820 /* set transparent colour on temp surface */ 3821 if (testing) { 3822 printf("About to setcolour ..."); 3823 fflush(STDOUT); 3824 } 3825 SDL_SetColorKey(temps, SDL_SRCCOLORKEY|SDL_RLEACCEL, bgcol); 3826 3827 /* blit to screen */ 3828 if (doublebuffer) { 3829 area.x = o->x; 3830 area.y = o->y; 3831 if (adjust) { 3832 area.x -= screenx; 3833 area.y -= screeny; 3834 } 3835 area.w = o->w; 3836 area.h = o->h; 3837 if (testing) { 3838 printf("About to blitsurface ..."); 3839 fflush(STDOUT); 3840 } 3841 SDL_BlitSurface(temps, 0, dest, &area); 3842 SDL_FreeSurface(temps); 3843 temps = NULL; 3844 } else { 3845 SDL_UpdateRect(temps, 0, 0, o->w, o->h); 3846 } 3847 3848 if (testing) { 3849 printf("About to return ..."); 3850 fflush(STDOUT); 3851 } 3852 3853 } 3854 3855 void drawobjectSVG(SDL_Surface *dest, mapobject_t *o, int doublebuffer) { 3856 static int gnum = 0; 3857 3858 /* create SVG group */ 3859 sprintf(svgbuf, "<g id=\"object%d\" >\n", gnum); 3860 fprintf(svgfile, svgbuf); 3861 3862 if (o->fillcol.unused & USECOLOUR) { 3863 drawvectorSVG(&objtype[o->type].vimg, o->x, o->y, o->w, o->h, NULL, &o->fillcol); 3864 } else { 3865 drawvectorSVG(&objtype[o->type].vimg, o->x, o->y, o->w, o->h, NULL, NULL); 3866 } 3867 3868 sprintf(svgbuf, "</g>\n"); 3869 fprintf(svgfile, svgbuf); 3870 gnum++; 3871 3872 } 3873 3874 void drawpixel(SDL_Surface *screen, int x, int y, SDL_Color c) { 3875 Uint32 color = SDL_MapRGB(screen->format, c.r, c.g, c.b); 3876 3877 if ((x < 0) || (y < 0) || (x >= screen->w) || (y >= screen->h)) { 3878 return; 3879 } 3880 3881 /*if ( SDL_MUSTLOCK(screen) ) { 3882 if ( SDL_LockSurface(screen) < 0 ) { 3883 return; 3884 } 3885 }*/ 3886 switch (screen->format->BytesPerPixel) { 3887 case 1: { /* Assuming 8-bpp */ 3888 Uint8 *bufp; 3889 3890 bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; 3891 *bufp = color; 3892 } 3893 break; 3894 3895 case 2: { /* Probably 15-bpp or 16-bpp */ 3896 Uint16 *bufp; 3897 3898 bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x; 3899 *bufp = color; 3900 } 3901 break; 3902 3903 case 3: { /* Slow 24-bpp mode, usually not used */ 3904 Uint8 *bufp; 3905 3906 bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3; 3907 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { 3908 bufp[0] = color; 3909 bufp[1] = color >> 8; 3910 bufp[2] = color >> 16; 3911 } else { 3912 bufp[2] = color; 3913 bufp[1] = color >> 8; 3914 bufp[0] = color >> 16; 3915 } 3916 } 3917 break; 3918 3919 case 4: { /* Probably 32-bpp */ 3920 Uint32 *bufp; 3921 3922 bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x; 3923 *bufp = color; 3924 } 3925 break; 3926 } 3927 /* 3928 if ( SDL_MUSTLOCK(screen) ) { 3929 SDL_UnlockSurface(screen); 3930 } 3931 */ 3932 //SDL_UpdateRect(screen, x, y, 1, 1); 3933 } 3934 3935 void drawmap(int wantdecs) { 3936 int i; 3937 int testing = 0; 3938 SDL_Rect area; 3939 Uint32 fillcol; 3940 int txoff,tyoff; 3941 int anchoreditem; 3942 int x,y; 3943 3944 for (i = 0; i < map[curmap].numthings; i++) { 3945 thingdrawn[i] = FALSE; 3946 } 3947 3948 if ((state == S_SAVING) || (state == S_LOADING) || (state == S_MAPNAMING) || (state == S_SEARCH)) { 3949 /* show text entry screen */ 3950 showfiledialog(); 3951 return; 3952 } 3953 3954 if ((state == S_FGCOL) || (state == S_FILLCOL)) { 3955 drawcolorchart(screen); 3956 return; 3957 } 3958 3959 if (state == S_CREATETELE) { 3960 drawmaplist(screen); 3961 return; 3962 } 3963 3964 if (state == S_REALLYQUIT) { 3965 drawyn(text); 3966 return; 3967 } 3968 3969 if (testing) { 3970 printf("START DRAWMAP\n"); fflush(STDOUT); 3971 } 3972 3973 /* clear map */ 3974 fillcol = SDL_MapRGB(buffer->format, map[curmap].bgcol.r,map[curmap].bgcol.g,map[curmap].bgcol.b); 3975 SDL_FillRect(buffer, NULL, fillcol); 3976 3977 /* draw grid */ 3978 if (gridsize != 0) { 3979 for (x = 0; x < screen->w - SIDEBARW; x += (gridsize*2)) { 3980 drawline(buffer,x,0,x,(screen->h - STATUSH), gridcol, (LS_BIGDASH << 8) | 1); 3981 if ((x+gridsize) < screen->w - SIDEBARW) { 3982 drawline(buffer,x+gridsize,0,x+gridsize,(screen->h - DEFTEXTH-2), gridcol, (LS_DOTTED << 8) | 1); 3983 } 3984 } 3985 3986 for (y = 0; y < screen->h - STATUSH; y += (gridsize*2)) { 3987 drawline(buffer,0,y,screen->w - SIDEBARW, y,gridcol, (LS_BIGDASH << 8) | 1); 3988 if ((y+gridsize) < (screen->h - STATUSH)) { 3989 drawline(buffer,0,y+gridsize,screen->w - SIDEBARW, y+gridsize,gridcol, (LS_DOTTED << 8) | 1); 3990 } 3991 } 3992 } 3993 3994 if (testing) { 3995 printf("DRAWING THINGS \n"); fflush(STDOUT); 3996 } 3997 3998 3999 /* draw all map[curmap].objects links etc*/ 4000 for (i = 0; i < map[curmap].numthings; i++) { 4001 if (map[curmap].thing[i].type == T_OBJECT) { 4002 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); } 4003 if (!isflow(map[curmap].thing[i].id, T_OBJECT)) { 4004 drawobject(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE, TRUE); 4005 thingdrawn[i] = TRUE; 4006 } 4007 } else if (map[curmap].thing[i].type == T_LINK) { 4008 if (testing) { printf ("Drawing thing #%d (%d, link)\n",i,map[curmap].thing[i].id); fflush(STDOUT); } 4009 if (!isflow(map[curmap].thing[i].id, T_LINK)) { 4010 drawlink(buffer, &map[curmap].olink[map[curmap].thing[i].id]); 4011 thingdrawn[i] = TRUE; 4012 } 4013 4014 } else if (map[curmap].thing[i].type == T_TEXT) { 4015 if (testing) { printf ("Drawing thing #%d (%d, text)\n",i,map[curmap].thing[i].id); fflush(STDOUT); } 4016 if (!isflow(map[curmap].thing[i].id, T_TEXT)) { 4017 drawtext(buffer, &map[curmap].textob[map[curmap].thing[i].id], TRUE); 4018 thingdrawn[i] = TRUE; 4019 } 4020 } else { 4021 printf("WARNING: Thing #%d has unknown type %d!\n",i,map[curmap].thing[i].type); 4022 thingdrawn[i] = TRUE; 4023 } 4024 } 4025 4026 /* show traffic flows (these should be on top of everything else) */ 4027 if (showflows) { 4028 for (i = 0; i < map[curmap].numthings; i++) { 4029 if (map[curmap].thing[i].type == T_OBJECT) { 4030 if (isflow(map[curmap].thing[i].id, T_OBJECT)) { 4031 drawobject(buffer, &map[curmap].obj[map[curmap].thing[i].id], TRUE, TRUE); 4032 if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_OBJECT); 4033 thingdrawn[i] = TRUE; 4034 } 4035 } else if (map[curmap].thing[i].type == T_LINK) { 4036 if (isflow(map[curmap].thing[i].id, T_LINK)) { 4037 drawlink(buffer, &map[curmap].olink[map[curmap].thing[i].id]); 4038 if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_LINK); 4039 thingdrawn[i] = TRUE; 4040 } 4041 } else if (map[curmap].thing[i].type == T_TEXT) { 4042 if (isflow(map[curmap].thing[i].id, T_TEXT)) { 4043 drawtext(buffer, &map[curmap].textob[map[curmap].thing[i].id], TRUE); 4044 if (state == S_DRAWFLOW) drawflowbox(buffer, map[curmap].thing[i].id, T_TEXT); 4045 thingdrawn[i] = TRUE; 4046 } 4047 } 4048 } 4049 } 4050 4051 if (testing) { 4052 printf("FINISHED THINGS \n"); fflush(STDOUT); 4053 } 4054 4055 if (testing) { 4056 printf("DRAWING HIGHLIGHT\n"); fflush(STDOUT); 4057 } 4058 4059 /* highlight the selected map[curmap].object */ 4060 /* by drawing boxes in its corners */ 4061 if (map[curmap].selecteditem != -1) { 4062 if (map[curmap].selecteditemtype == T_OBJECT) { 4063 int n; 4064 4065 /* 10% of map[curmap].object's size */ 4066 area.w = map[curmap].obj[map[curmap].selecteditem].w / OBJSELHANDLEPCT; 4067 area.h = map[curmap].obj[map[curmap].selecteditem].h / OBJSELHANDLEPCT; 4068 if (area.w < 2) area.w = 2; 4069 if (area.h < 2) area.h = 2; 4070 4071 fillcol = SDL_MapRGB(buffer->format, 0, 0, 0); 4072 4073 /* top left */ 4074 area.x = map[curmap].obj[map[curmap].selecteditem].x - screenx; 4075 area.y = map[curmap].obj[map[curmap].selecteditem].y - screeny; 4076 SDL_FillRect(buffer, &area, fillcol); 4077 /* top right */ 4078 area.x = map[curmap].obj[map[curmap].selecteditem].x + map[curmap].obj[map[curmap].selecteditem].w - area.w - screenx; 4079 area.y = map[curmap].obj[map[curmap].selecteditem].y - screeny; 4080 SDL_FillRect(buffer, &area, fillcol); 4081 /* bottom left */ 4082 area.x = map[curmap].obj[map[curmap].selecteditem].x - screenx; 4083 area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h - screeny; 4084 SDL_FillRect(buffer, &area, fillcol); 4085 /* bottom right */ 4086 area.x = map[curmap].obj[map[curmap].selecteditem].x + map[curmap].obj[map[curmap].selecteditem].w - area.w - screenx; 4087 area.y = map[curmap].obj[map[curmap].selecteditem].y + map[curmap].obj[map[curmap].selecteditem].h - area.h - screeny; 4088 SDL_FillRect(buffer, &area, fillcol); 4089 4090 /* Also highlight any text anchored to this object */ 4091 for (n = 0; n < map[curmap].numtext; n++) { 4092 if (map[curmap].textob[n].anchor == map[curmap].selecteditem) { 4093 int th; 4094 4095 /* calculate text's height */ 4096 th = TTF_FontHeight(font[map[curmap].textob[n].h]); 4097 4098 /* 10% of text's size */ 4099 area.w = map[curmap].textob[n].w / OBJSELHANDLEPCT; 4100 area.h = th / OBJSELHANDLEPCT; 4101 if (area.w < 2) area.w = 2; 4102 if (area.h < 2) area.h = 2; 4103 4104 anchoreditem = map[curmap].textob[n].anchor; 4105 if (anchoreditem == -1) { 4106 txoff = 0; 4107 tyoff = 0; 4108 } else { 4109 txoff = map[curmap].obj[anchoreditem].x; 4110 tyoff = map[curmap].obj[anchoreditem].y; 4111 } 4112 4113 fillcol = SDL_MapRGB(buffer->format, 0, 255, 0); 4114 4115 /* top left */ 4116 area.x = map[curmap].textob[n].x + txoff - screenx; 4117 area.y = map[curmap].textob[n].y + tyoff - screeny; 4118 SDL_FillRect(buffer, &area, fillcol); 4119 /* top right */ 4120 area.x = map[curmap].textob[n].x +txoff + map[curmap].textob[n].w - area.w - screenx; 4121 area.y = map[curmap].textob[n].y + tyoff - screeny; 4122 SDL_FillRect(buffer, &area, fillcol); 4123 /* bottom left */ 4124 area.x = map[curmap].textob[n].x +txoff - screenx; 4125 area.y = map[curmap].textob[n].y + tyoff + th - area.h - screeny; 4126 SDL_FillRect(buffer, &area, fillcol); 4127 /* bottom right */ 4128 area.x = map[curmap].textob[n].x+txoff + map[curmap].textob[n].w - area.w - screenx; 4129 area.y = map[curmap].textob[n].y +tyoff+ th - area.h - screeny; 4130 SDL_FillRect(buffer, &area, fillcol); 4131 } 4132 } 4133 4134 } else if (map[curmap].selecteditemtype == T_TEXT) { 4135 int th; 4136 4137 /* calculate text's height */ 4138 th = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); 4139 4140 /* 10% of text's size */ 4141 area.w = map[curmap].textob[map[curmap].selecteditem].w / OBJSELHANDLEPCT; 4142 area.h = th / OBJSELHANDLEPCT; 4143 if (area.w < 2) area.w = 2; 4144 if (area.h < 2) area.h = 2; 4145 4146 anchoreditem = map[curmap].textob[map[curmap].selecteditem].anchor; 4147 if (anchoreditem == -1) { 4148 txoff = 0; 4149 tyoff = 0; 4150 } else { 4151 txoff = map[curmap].obj[anchoreditem].x; 4152 tyoff = map[curmap].obj[anchoreditem].y; 4153 } 4154 4155 fillcol = SDL_MapRGB(buffer->format, 0, 0, 0); 4156 4157 /* top left */ 4158 area.x = map[curmap].textob[map[curmap].selecteditem].x + txoff - screenx; 4159 area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff - screeny; 4160 SDL_FillRect(buffer, &area, fillcol); 4161 /* top right */ 4162 area.x = map[curmap].textob[map[curmap].selecteditem].x +txoff + map[curmap].textob[map[curmap].selecteditem].w - area.w - screenx; 4163 area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff - screeny; 4164 SDL_FillRect(buffer, &area, fillcol); 4165 /* bottom left */ 4166 area.x = map[curmap].textob[map[curmap].selecteditem].x +txoff - screenx; 4167 area.y = map[curmap].textob[map[curmap].selecteditem].y + tyoff + th - area.h - screeny; 4168 SDL_FillRect(buffer, &area, fillcol); 4169 /* bottom right */ 4170 area.x = map[curmap].textob[map[curmap].selecteditem].x+txoff + map[curmap].textob[map[curmap].selecteditem].w - area.w - screenx; 4171 area.y = map[curmap].textob[map[curmap].selecteditem].y +tyoff+ th - area.h - screeny; 4172 SDL_FillRect(buffer, &area, fillcol); 4173 4174 /* if this text is anchored, highlight the map[curmap].object which it is anchored to */ 4175 if (anchoreditem != -1) { 4176 area.w = map[curmap].obj[anchoreditem].w / OBJSELHANDLEPCT; 4177 area.h = map[curmap].obj[anchoreditem].h / OBJSELHANDLEPCT; 4178 if (area.w < 2) area.w = 2; 4179 if (area.h < 2) area.h = 2; 4180 4181 fillcol = SDL_MapRGB(buffer->format, 0, 255, 0); 4182 4183 /* top left */ 4184 area.x = map[curmap].obj[anchoreditem].x - screenx; 4185 area.y = map[curmap].obj[anchoreditem].y - screeny; 4186 SDL_FillRect(buffer, &area, fillcol); 4187 /* top right */ 4188 area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w - screenx; 4189 area.y = map[curmap].obj[anchoreditem].y - screeny; 4190 SDL_FillRect(buffer, &area, fillcol); 4191 /* bottom left */ 4192 area.x = map[curmap].obj[anchoreditem].x - screenx; 4193 area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h - screeny; 4194 SDL_FillRect(buffer, &area, fillcol); 4195 /* bottom right */ 4196 area.x = map[curmap].obj[anchoreditem].x + map[curmap].obj[anchoreditem].w - area.w - screenx; 4197 area.y = map[curmap].obj[anchoreditem].y + map[curmap].obj[anchoreditem].h - area.h - screeny; 4198 SDL_FillRect(buffer, &area, fillcol); 4199 } 4200 4201 } else if (map[curmap].selecteditemtype == T_LINK) { 4202 /* 10% of map[curmap].object's size */ 4203 area.w = LINESELHANDLESIZE; 4204 area.h = LINESELHANDLESIZE; 4205 4206 fillcol = SDL_MapRGB(buffer->format, 0, 0, 0); 4207 4208 /* start of line */ 4209 area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].x + map[curmap].olink[map[curmap].selecteditem].srcxoff - (LINESELHANDLESIZE/2) - screenx; 4210 area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2) - screeny; 4211 SDL_FillRect(buffer, &area, fillcol); 4212 /* end of line */ 4213 area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].x + map[curmap].olink[map[curmap].selecteditem].dstxoff - (LINESELHANDLESIZE/2) - screenx; 4214 area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2) - screeny; 4215 SDL_FillRect(buffer, &area, fillcol); 4216 4217 /* points on the line */ 4218 for (i = 0; i < map[curmap].olink[map[curmap].selecteditem].npoints; i++) { 4219 area.x = map[curmap].olink[map[curmap].selecteditem].point[i].x - (LINESELHANDLESIZE/2) - screenx; 4220 area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2) - screeny; 4221 SDL_FillRect(buffer, &area, fillcol); 4222 } 4223 } else if (map[curmap].selecteditemtype == T_LINKPOINT) { 4224 /* highlight the line in green */ 4225 /* 10% of map[curmap].object's size */ 4226 area.w = LINESELHANDLESIZE; 4227 area.h = LINESELHANDLESIZE; 4228 4229 fillcol = SDL_MapRGB(buffer->format, 0, 255, 0); 4230 4231 /* start of line */ 4232 area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].x + map[curmap].olink[map[curmap].selecteditem].srcxoff - (LINESELHANDLESIZE/2) - screenx; 4233 area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].srcobj].y + map[curmap].olink[map[curmap].selecteditem].srcyoff - (LINESELHANDLESIZE/2) - screeny; 4234 SDL_FillRect(buffer, &area, fillcol); 4235 /* end of line */ 4236 area.x = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].x + map[curmap].olink[map[curmap].selecteditem].dstxoff - (LINESELHANDLESIZE/2) - screenx; 4237 area.y = map[curmap].obj[map[curmap].olink[map[curmap].selecteditem].dstobj].y + map[curmap].olink[map[curmap].selecteditem].dstyoff - (LINESELHANDLESIZE/2) - screeny; 4238 SDL_FillRect(buffer, &area, fillcol); 4239 4240 /* points on the line */ 4241 for (i = 0; i < map[curmap].olink[map[curmap].selecteditem].npoints; i++) { 4242 if (i == map[curmap].selectedlinkpoint) { 4243 fillcol = SDL_MapRGB(buffer->format, 0, 0, 0); 4244 } else { 4245 fillcol = SDL_MapRGB(buffer->format, 0, 255, 0); 4246 } 4247 area.x = map[curmap].olink[map[curmap].selecteditem].point[i].x - (LINESELHANDLESIZE/2) - screenx; 4248 area.y = map[curmap].olink[map[curmap].selecteditem].point[i].y - (LINESELHANDLESIZE/2) - screeny; 4249 SDL_FillRect(buffer, &area, fillcol); 4250 } 4251 } 4252 } 4253 4254 /* blit buffer to screen */ 4255 SDL_BlitSurface(buffer, 0, screen,0); 4256 4257 if (testing) { 4258 printf("START MAPBOX\n"); fflush(STDOUT); 4259 } 4260 drawmapbox(); 4261 4262 /* draw status bar */ 4263 if (wantdecs) { 4264 if (testing) { 4265 printf("START STATUSBAR\n"); fflush(STDOUT); 4266 } 4267 drawstatusbar(); 4268 } 4269 4270 if (testing) { 4271 printf("FLIP\n"); fflush(STDOUT); 4272 } 4273 4274 if (wantdecs) { 4275 /* draw scrollbars, if required */ 4276 if (map[curmap].width > (screen->w - SIDEBARW)) { 4277 drawxscrollbar(); 4278 } 4279 if (map[curmap].height > (screen->h - STATUSH)) { 4280 drawyscrollbar(); 4281 } 4282 } 4283 4284 /* calculate mapdimensions if diagram has been modified */ 4285 if (needtocalc) { 4286 calcmapdimensions(); 4287 needtocalc = FALSE; 4288 } 4289 4290 /* flip */ 4291 SDL_Flip(screen); 4292 //SDL_UpdateRect(screen, 0, 0, map[curmap].width, map[curmap].height); 4293 } 4294 4295 void drawxscrollbar(void) { 4296 int barw; 4297 double barx; 4298 4299 barx = ((double)screenx / (double)map[curmap].width) * (screen->w - SIDEBARW - SBSIZE); 4300 4301 /* scrollbar outline */ 4302 drawbox(screen, 0, screen->h - STATUSH - SBSIZE, 4303 screen->w - SIDEBARW - SBSIZE, screen->h - STATUSH - 1, blue2 , &blue2); 4304 4305 /* screen position */ 4306 barw = (((double)(screen->w - SIDEBARW - SBSIZE) / (double)map[curmap].width) * (screen->w - SIDEBARW - SBSIZE)); 4307 if (barx+barw > (screen->w - SIDEBARW-SBSIZE)) barw = screen->w - SIDEBARW - SBSIZE - barx; 4308 4309 drawbox(screen, barx, screen->h - STATUSH - SBSIZE+1, 4310 barx + barw, screen->h - STATUSH - 2, blue , &blue); 4311 4312 SDL_UpdateRect(screen, 0,screen->h - STATUSH - SBSIZE, screen->w, SBSIZE); 4313 } 4314 4315 void drawyscrollbar(void) { 4316 int barh; 4317 double bary; 4318 4319 bary = ((double)screeny / (double)map[curmap].height) * (screen->h - STATUSH - SBSIZE); 4320 4321 /* scrollbar outline */ 4322 drawbox(screen, screen->w - SIDEBARW - SBSIZE, 0, 4323 screen->w - SIDEBARW - 2, screen->h - STATUSH - SBSIZE - 1, blue2, &blue2); 4324 4325 /* screen position */ 4326 barh = (((double)(screen->h - STATUSH - SBSIZE) / (double)map[curmap].height) * (screen->h - STATUSH - SBSIZE)); 4327 if (bary+barh > (screen->h - STATUSH - SBSIZE)) barh = screen->h - STATUSH - SBSIZE - bary; 4328 4329 drawbox(screen, screen->w - SIDEBARW - SBSIZE+1, bary, 4330 screen->w - SIDEBARW - 3, bary + barh, blue , &blue); 4331 4332 SDL_UpdateRect(screen, screen->w - SIDEBARW - SBSIZE, 0, SBSIZE, screen->h - STATUSH - SBSIZE - 1); 4333 } 4334 4335 void validatescreenpos(void) { 4336 if (screenx + (screen->w - SIDEBARW) > map[curmap].width) { 4337 screenx = map[curmap].width - (screen->w - SIDEBARW); 4338 } 4339 if (screenx < 0) screenx = 0; 4340 4341 if (screeny + (screen->h - STATUSH) > map[curmap].height) { 4342 screeny = map[curmap].height - (screen->h - STATUSH); 4343 } 4344 if (screeny < 0) screeny = 0; 4345 } 4346 4347 void drawsearchflash(void) { 4348 SDL_Surface *temps; 4349 SDL_Rect area; 4350 int txoff,tyoff; 4351 int anchoreditem; 4352 4353 4354 if (!searchflash) { 4355 return; 4356 } 4357 /* highlight the object just found in a search */ 4358 if (map[curmap].selecteditem != -1) { 4359 if (map[curmap].selecteditemtype == T_TEXT) { 4360 int th; 4361 4362 /* calculate text's height */ 4363 th = TTF_FontHeight(font[map[curmap].textob[map[curmap].selecteditem].h]); 4364 4365 area.w = map[curmap].textob[map[curmap].selecteditem].w; 4366 area.h = th; 4367 4368