| 1 | // This file is part of SmallBASIC | 
|---|
| 2 | // | 
|---|
| 3 | // SmallBASIC RTL - GRAPHICS | 
|---|
| 4 | // | 
|---|
| 5 | // This program is distributed under the terms of the GPL v2.0 or later | 
|---|
| 6 | // Download the GNU Public License (GPL) from www.gnu.org | 
|---|
| 7 | // | 
|---|
| 8 | // Copyright(C) 2000 Nicholas Christopoulos | 
|---|
| 9 |  | 
|---|
| 10 | #include "common/pproc.h" | 
|---|
| 11 | #include "common/messages.h" | 
|---|
| 12 |  | 
|---|
| 13 | // graphics - relative coordinates | 
|---|
| 14 | int gra_x; | 
|---|
| 15 | int gra_y; | 
|---|
| 16 |  | 
|---|
| 17 | void graph_reset() { | 
|---|
| 18 | gra_x = gra_y = 0; | 
|---|
| 19 | } | 
|---|
| 20 |  | 
|---|
| 21 | // | 
|---|
| 22 | //  VIEW [x1,y1,x2,y2[,c[,b]]] | 
|---|
| 23 | // | 
|---|
| 24 | void cmd_view() { | 
|---|
| 25 | ipt_t p1, p2; | 
|---|
| 26 | int32_t prev_color = dev_fgcolor; | 
|---|
| 27 | int32_t color = dev_bgcolor; | 
|---|
| 28 | int32_t bcolor = -1; | 
|---|
| 29 |  | 
|---|
| 30 | if (code_peek() != kwTYPE_EOC && code_peek() != kwTYPE_LINE) { | 
|---|
| 31 | p1 = par_getipt(); | 
|---|
| 32 | if (prog_error) | 
|---|
| 33 | return; | 
|---|
| 34 | par_getcomma(); | 
|---|
| 35 | if (prog_error) | 
|---|
| 36 | return; | 
|---|
| 37 | p2 = par_getipt(); | 
|---|
| 38 | if (prog_error) | 
|---|
| 39 | return; | 
|---|
| 40 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 41 | par_getcomma(); | 
|---|
| 42 | if (prog_error) | 
|---|
| 43 | return; | 
|---|
| 44 | color = par_getint(); | 
|---|
| 45 | if (prog_error) | 
|---|
| 46 | return; | 
|---|
| 47 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 48 | par_getcomma(); | 
|---|
| 49 | if (prog_error) | 
|---|
| 50 | return; | 
|---|
| 51 | bcolor = par_getint(); | 
|---|
| 52 | if (prog_error) | 
|---|
| 53 | return; | 
|---|
| 54 | } | 
|---|
| 55 | } | 
|---|
| 56 |  | 
|---|
| 57 | dev_setcolor(color); | 
|---|
| 58 | dev_rect(p1.x, p1.y, p2.x, p2.y, 1); | 
|---|
| 59 | if (bcolor != -1) { | 
|---|
| 60 | dev_setcolor(bcolor); | 
|---|
| 61 | dev_rect(p1.x - 1, p1.y - 1, p2.x + 1, p2.y + 1, 0); | 
|---|
| 62 | } | 
|---|
| 63 | dev_setcolor(prev_color); | 
|---|
| 64 | dev_viewport(p1.x, p1.y, p2.x, p2.y); | 
|---|
| 65 | } else { | 
|---|
| 66 | dev_viewport(0, 0, 0, 0); | 
|---|
| 67 | } | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | // | 
|---|
| 71 | //  WINDOW [x1,y1,x2,y2] | 
|---|
| 72 | // | 
|---|
| 73 | void cmd_window() { | 
|---|
| 74 | ipt_t p1, p2; | 
|---|
| 75 |  | 
|---|
| 76 | if (code_peek() != kwTYPE_EOC && code_peek() != kwTYPE_LINE) { | 
|---|
| 77 | p1 = par_getipt(); | 
|---|
| 78 | if (prog_error) | 
|---|
| 79 | return; | 
|---|
| 80 | par_getcomma(); | 
|---|
| 81 | if (prog_error) | 
|---|
| 82 | return; | 
|---|
| 83 | p2 = par_getipt(); | 
|---|
| 84 | if (prog_error) | 
|---|
| 85 | return; | 
|---|
| 86 | dev_window(p1.x, p2.y, p2.x, p1.y); // QB compatible | 
|---|
| 87 | // dev_window(p1.x, p1.y, p2.x, p2.y); // SB default (logical one) | 
|---|
| 88 | } else { | 
|---|
| 89 | dev_window(0, 0, 0, 0); | 
|---|
| 90 | } | 
|---|
| 91 | } | 
|---|
| 92 |  | 
|---|
| 93 | // | 
|---|
| 94 | //  PSET [STEP] x, y [, color | COLOR color] | 
|---|
| 95 | // | 
|---|
| 96 | void cmd_pset() { | 
|---|
| 97 | long color = dev_fgcolor; | 
|---|
| 98 | int32_t step1 = 0; | 
|---|
| 99 | ipt_t pt; | 
|---|
| 100 |  | 
|---|
| 101 | /* | 
|---|
| 102 | * [STEP] x, y | 
|---|
| 103 | */ | 
|---|
| 104 | if (code_peek() == kwSTEP) { | 
|---|
| 105 | code_skipnext(); | 
|---|
| 106 | step1 = 1; | 
|---|
| 107 | } | 
|---|
| 108 |  | 
|---|
| 109 | pt = par_getipt(); | 
|---|
| 110 | if (step1) | 
|---|
| 111 | (pt.x += gra_x, pt.y += gra_y); | 
|---|
| 112 |  | 
|---|
| 113 | if (code_peek() == kwCOLOR) { | 
|---|
| 114 | code_skipnext(); | 
|---|
| 115 | color = par_getint(); | 
|---|
| 116 | if (prog_error) | 
|---|
| 117 | return; | 
|---|
| 118 | } | 
|---|
| 119 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 120 | par_getcomma(); | 
|---|
| 121 | if (prog_error) | 
|---|
| 122 | return; | 
|---|
| 123 | color = par_getint(); | 
|---|
| 124 | if (prog_error) | 
|---|
| 125 | return; | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 | gra_x = pt.x; | 
|---|
| 129 | gra_y = pt.y; | 
|---|
| 130 |  | 
|---|
| 131 | if (color != dev_fgcolor) { | 
|---|
| 132 | int prev_color = dev_fgcolor; | 
|---|
| 133 |  | 
|---|
| 134 | dev_setcolor(color); | 
|---|
| 135 | dev_setpixel(pt.x, pt.y); | 
|---|
| 136 | dev_setcolor(prev_color); | 
|---|
| 137 | } else | 
|---|
| 138 | dev_setpixel(pt.x, pt.y); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | // | 
|---|
| 142 | //  LINE [STEP] x, y [{,|STEP} x2, y2] [, color | COLOR color] | 
|---|
| 143 | // | 
|---|
| 144 | void cmd_line() { | 
|---|
| 145 | ipt_t p1, p2; | 
|---|
| 146 | byte step = 0; | 
|---|
| 147 | int32_t color = dev_fgcolor; | 
|---|
| 148 |  | 
|---|
| 149 | /* | 
|---|
| 150 | * [STEP] x, y | 
|---|
| 151 | */ | 
|---|
| 152 | if (code_peek() == kwSTEP) { | 
|---|
| 153 | code_skipnext(); | 
|---|
| 154 | step = 1; | 
|---|
| 155 | } | 
|---|
| 156 |  | 
|---|
| 157 | p1 = par_getipt(); | 
|---|
| 158 | if (step) { | 
|---|
| 159 | (p1.x += gra_x, p1.y += gra_y, step = 0); | 
|---|
| 160 | } | 
|---|
| 161 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 162 | par_getcomma(); | 
|---|
| 163 | } | 
|---|
| 164 | /* | 
|---|
| 165 | * x, y [,] ---> [STEP] ? | 
|---|
| 166 | */ | 
|---|
| 167 | if (code_peek() == kwSTEP) { | 
|---|
| 168 | code_skipnext(); | 
|---|
| 169 | step = 1; | 
|---|
| 170 | } | 
|---|
| 171 |  | 
|---|
| 172 | if (code_peek() != kwCOLOR && code_peek() != kwTYPE_EOC && code_peek() != kwTYPE_LINE) { | 
|---|
| 173 | /* | 
|---|
| 174 | * [STEP] x, y [[,]STEP] ---> x2, y2 | 
|---|
| 175 | */ | 
|---|
| 176 | p2 = par_getipt(); | 
|---|
| 177 | if (step) | 
|---|
| 178 | (p2.x += p1.x, p2.y += p1.y); | 
|---|
| 179 | } else { | 
|---|
| 180 | p2 = p1; | 
|---|
| 181 | p1.x = gra_x; | 
|---|
| 182 | p1.y = gra_y; | 
|---|
| 183 | } | 
|---|
| 184 |  | 
|---|
| 185 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 186 | par_getcomma(); | 
|---|
| 187 | if (prog_error) | 
|---|
| 188 | return; | 
|---|
| 189 | color = par_getint(); | 
|---|
| 190 | if (prog_error) | 
|---|
| 191 | return; | 
|---|
| 192 | } | 
|---|
| 193 | if (code_peek() == kwCOLOR) { | 
|---|
| 194 | code_skipnext(); | 
|---|
| 195 | color = par_getint(); | 
|---|
| 196 | if (prog_error) | 
|---|
| 197 | return; | 
|---|
| 198 | } | 
|---|
| 199 |  | 
|---|
| 200 | /* | 
|---|
| 201 | * draw | 
|---|
| 202 | */ | 
|---|
| 203 | gra_x = p2.x; | 
|---|
| 204 | gra_y = p2.y; | 
|---|
| 205 |  | 
|---|
| 206 | if (color != dev_fgcolor) { | 
|---|
| 207 | int32_t prev_color = dev_fgcolor; | 
|---|
| 208 |  | 
|---|
| 209 | dev_setcolor(color); | 
|---|
| 210 | dev_line(p1.x, p1.y, p2.x, p2.y); | 
|---|
| 211 | dev_setcolor(prev_color); | 
|---|
| 212 | } else | 
|---|
| 213 | dev_line(p1.x, p1.y, p2.x, p2.y); | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|
| 216 | // | 
|---|
| 217 | //  RECT [STEP] x, y [{,|STEP} x2, y2] [COLOR color] [FILLED] | 
|---|
| 218 | // | 
|---|
| 219 | void cmd_rect() { | 
|---|
| 220 | ipt_t p1, p2; | 
|---|
| 221 | int32_t color = dev_fgcolor; | 
|---|
| 222 | byte fill = 0, step = 0; | 
|---|
| 223 |  | 
|---|
| 224 | /* | 
|---|
| 225 | * [STEP] x, y | 
|---|
| 226 | */ | 
|---|
| 227 | if (code_peek() == kwSTEP) { | 
|---|
| 228 | code_skipnext(); | 
|---|
| 229 | step = 1; | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | p1 = par_getipt(); | 
|---|
| 233 | if (step) | 
|---|
| 234 | (p1.x += gra_x, p1.y += gra_y, step = 0); | 
|---|
| 235 |  | 
|---|
| 236 | if (code_peek() == kwTYPE_SEP) | 
|---|
| 237 | par_getcomma(); | 
|---|
| 238 |  | 
|---|
| 239 | /* | 
|---|
| 240 | * x, y [,] ---> [STEP] ? | 
|---|
| 241 | */ | 
|---|
| 242 | if (code_peek() == kwSTEP) { | 
|---|
| 243 | code_skipnext(); | 
|---|
| 244 | step = 1; | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | if (code_peek() != kwCOLOR && code_peek() != kwFILLED && code_peek() != kwTYPE_EOC | 
|---|
| 248 | && code_peek() != kwTYPE_LINE) { | 
|---|
| 249 | /* | 
|---|
| 250 | * [STEP] x, y [[,]STEP] ---> x2, y2 | 
|---|
| 251 | */ | 
|---|
| 252 | p2 = par_getipt(); | 
|---|
| 253 | if (step) | 
|---|
| 254 | (p2.x += p1.x, p2.y += p1.y); | 
|---|
| 255 | } else { | 
|---|
| 256 | p2 = p1; | 
|---|
| 257 | p1.x = gra_x; | 
|---|
| 258 | p1.y = gra_y; | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 262 | par_getcomma(); | 
|---|
| 263 | if (prog_error) | 
|---|
| 264 | return; | 
|---|
| 265 | color = par_getint(); | 
|---|
| 266 | if (prog_error) | 
|---|
| 267 | return; | 
|---|
| 268 | } | 
|---|
| 269 | if (code_peek() == kwCOLOR) { | 
|---|
| 270 | code_skipnext(); | 
|---|
| 271 | color = par_getint(); | 
|---|
| 272 | if (prog_error) | 
|---|
| 273 | return; | 
|---|
| 274 | } | 
|---|
| 275 | if (code_peek() == kwFILLED) { | 
|---|
| 276 | code_skipnext(); | 
|---|
| 277 | fill = 1; | 
|---|
| 278 | } | 
|---|
| 279 |  | 
|---|
| 280 | /* | 
|---|
| 281 | * draw | 
|---|
| 282 | */ | 
|---|
| 283 | gra_x = p2.x; | 
|---|
| 284 | gra_y = p2.y; | 
|---|
| 285 |  | 
|---|
| 286 | if (color != dev_fgcolor) { | 
|---|
| 287 | int prev_color = dev_fgcolor; | 
|---|
| 288 |  | 
|---|
| 289 | dev_setcolor(color); | 
|---|
| 290 | dev_rect(p1.x, p1.y, p2.x, p2.y, fill); | 
|---|
| 291 | dev_setcolor(prev_color); | 
|---|
| 292 | } else | 
|---|
| 293 | dev_rect(p1.x, p1.y, p2.x, p2.y, fill); | 
|---|
| 294 | } | 
|---|
| 295 |  | 
|---|
| 296 | // | 
|---|
| 297 | //  DRAWPOLY v() [, xorg, yorg [, scale[, color]] [COLOR color] [FILLED] | 
|---|
| 298 | // | 
|---|
| 299 | //  0,2,4... x | 
|---|
| 300 | //  1,3,5... y | 
|---|
| 301 | // | 
|---|
| 302 | void cmd_drawpoly() { | 
|---|
| 303 | int i, count; | 
|---|
| 304 | var_num_t xorg = 0, yorg = 0; | 
|---|
| 305 | int32_t prev_color = dev_fgcolor; | 
|---|
| 306 | int32_t color = dev_fgcolor; | 
|---|
| 307 | byte filled = 0, scalef = 0; | 
|---|
| 308 | var_num_t scale = 1.0; | 
|---|
| 309 | ipt_t *poly = NULL; | 
|---|
| 310 |  | 
|---|
| 311 | // array | 
|---|
| 312 | count = par_getipoly(&poly); | 
|---|
| 313 | if (prog_error) { | 
|---|
| 314 | free(poly); | 
|---|
| 315 | return; | 
|---|
| 316 | } | 
|---|
| 317 | if (count == 0) { | 
|---|
| 318 | free(poly); | 
|---|
| 319 | return; | 
|---|
| 320 | } | 
|---|
| 321 | // x,y origin | 
|---|
| 322 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 323 | par_getcomma(); | 
|---|
| 324 | if (!prog_error) { | 
|---|
| 325 | xorg = par_getreal(); | 
|---|
| 326 | if (!prog_error) { | 
|---|
| 327 | par_getcomma(); | 
|---|
| 328 | if (!prog_error) | 
|---|
| 329 | yorg = par_getreal(); | 
|---|
| 330 | } | 
|---|
| 331 | } | 
|---|
| 332 |  | 
|---|
| 333 | if (prog_error) { | 
|---|
| 334 | free(poly); | 
|---|
| 335 | return; | 
|---|
| 336 | } | 
|---|
| 337 |  | 
|---|
| 338 | // scale factor | 
|---|
| 339 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 340 | par_getcomma(); | 
|---|
| 341 | if (!prog_error) { | 
|---|
| 342 | scale = par_getnum(); | 
|---|
| 343 | if (!prog_error) { | 
|---|
| 344 | scalef++; | 
|---|
| 345 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 346 | par_getcomma(); | 
|---|
| 347 | if (!prog_error) | 
|---|
| 348 | color = par_getint(); | 
|---|
| 349 | } | 
|---|
| 350 | } | 
|---|
| 351 | } | 
|---|
| 352 | } | 
|---|
| 353 |  | 
|---|
| 354 | if (prog_error) { | 
|---|
| 355 | free(poly); | 
|---|
| 356 | return; | 
|---|
| 357 | } | 
|---|
| 358 | } | 
|---|
| 359 |  | 
|---|
| 360 | // color | 
|---|
| 361 | if (code_peek() == kwCOLOR) { | 
|---|
| 362 | code_skipnext(); | 
|---|
| 363 | color = par_getint(); | 
|---|
| 364 | if (prog_error) { | 
|---|
| 365 | free(poly); | 
|---|
| 366 | return; | 
|---|
| 367 | } | 
|---|
| 368 | } | 
|---|
| 369 |  | 
|---|
| 370 | // filled | 
|---|
| 371 | if (code_peek() == kwFILLED) { | 
|---|
| 372 | code_skipnext(); | 
|---|
| 373 | filled++; | 
|---|
| 374 | } | 
|---|
| 375 |  | 
|---|
| 376 | // scale it and move it | 
|---|
| 377 | if (scalef || xorg != 0 || yorg != 0) { | 
|---|
| 378 | if (scalef) { | 
|---|
| 379 | for (i = 0; i < count; i++) { | 
|---|
| 380 | poly[i].x = xorg + poly[i].x * scale; | 
|---|
| 381 | poly[i].y = yorg + poly[i].y * scale; | 
|---|
| 382 | } | 
|---|
| 383 | } else { | 
|---|
| 384 | for (i = 0; i < count; i++) { | 
|---|
| 385 | poly[i].x = xorg + poly[i].x; | 
|---|
| 386 | poly[i].y = yorg + poly[i].y; | 
|---|
| 387 | } | 
|---|
| 388 | } | 
|---|
| 389 | } | 
|---|
| 390 |  | 
|---|
| 391 | // ready | 
|---|
| 392 | if (color != dev_fgcolor) | 
|---|
| 393 | dev_setcolor(color); | 
|---|
| 394 |  | 
|---|
| 395 | if (!filled) { | 
|---|
| 396 | for (i = 1; i < count; i++) | 
|---|
| 397 | dev_line(poly[i - 1].x, poly[i - 1].y, poly[i].x, poly[i].y); | 
|---|
| 398 | } else | 
|---|
| 399 | dev_pfill(poly, count); | 
|---|
| 400 |  | 
|---|
| 401 | // cleanup | 
|---|
| 402 | free(poly); | 
|---|
| 403 |  | 
|---|
| 404 | if (color != prev_color) | 
|---|
| 405 | dev_setcolor(prev_color); | 
|---|
| 406 | } | 
|---|
| 407 |  | 
|---|
| 408 | // | 
|---|
| 409 | //  CIRCLE [STEP] x, y, r [, aspect[, color]] [COLOR color] [FILLED] | 
|---|
| 410 | // | 
|---|
| 411 | void cmd_circle() { | 
|---|
| 412 | int32_t color = dev_fgcolor; | 
|---|
| 413 | byte fill = 0, step = 0; | 
|---|
| 414 | ipt_t pt; | 
|---|
| 415 | int r; | 
|---|
| 416 | var_num_t aspect = 1.0; | 
|---|
| 417 | byte code; | 
|---|
| 418 |  | 
|---|
| 419 | /* | 
|---|
| 420 | * [STEP] x, y | 
|---|
| 421 | */ | 
|---|
| 422 | code = code_peek(); | 
|---|
| 423 | if (code == kwSTEP) { | 
|---|
| 424 | code_skipnext(); | 
|---|
| 425 | step = 1; | 
|---|
| 426 | } | 
|---|
| 427 |  | 
|---|
| 428 | // xc,yc | 
|---|
| 429 | pt = par_getipt(); | 
|---|
| 430 | if (prog_error) | 
|---|
| 431 | return; | 
|---|
| 432 | // r | 
|---|
| 433 | par_getcomma(); | 
|---|
| 434 | if (prog_error) | 
|---|
| 435 | return; | 
|---|
| 436 | r = par_getint(); | 
|---|
| 437 | if (prog_error) | 
|---|
| 438 | return; | 
|---|
| 439 | if (step) | 
|---|
| 440 | (pt.x += gra_x, pt.y += gra_y); | 
|---|
| 441 |  | 
|---|
| 442 | // aspect | 
|---|
| 443 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 444 | par_getcomma(); | 
|---|
| 445 | if (prog_error) | 
|---|
| 446 | return; | 
|---|
| 447 | aspect = par_getnum(); | 
|---|
| 448 | if (prog_error) | 
|---|
| 449 | return; | 
|---|
| 450 |  | 
|---|
| 451 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 452 | par_getcomma(); | 
|---|
| 453 | if (prog_error) | 
|---|
| 454 | return; | 
|---|
| 455 | color = par_getint(); | 
|---|
| 456 | if (prog_error) | 
|---|
| 457 | return; | 
|---|
| 458 | } | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|
| 461 | // COLOR | 
|---|
| 462 | if (code_peek() == kwCOLOR) { | 
|---|
| 463 | code_skipnext(); | 
|---|
| 464 | color = par_getint(); | 
|---|
| 465 | if (prog_error) | 
|---|
| 466 | return; | 
|---|
| 467 | } | 
|---|
| 468 |  | 
|---|
| 469 | // FILLED | 
|---|
| 470 | if (code_peek() == kwFILLED) { | 
|---|
| 471 | code_skipnext(); | 
|---|
| 472 | fill = 1; | 
|---|
| 473 | } | 
|---|
| 474 |  | 
|---|
| 475 | if (color != dev_fgcolor) { | 
|---|
| 476 | int32_t prev_color = dev_fgcolor; | 
|---|
| 477 |  | 
|---|
| 478 | dev_setcolor(color); | 
|---|
| 479 | dev_ellipse(pt.x, pt.y, r, r, aspect, fill); | 
|---|
| 480 | dev_setcolor(prev_color); | 
|---|
| 481 | } else | 
|---|
| 482 | dev_ellipse(pt.x, pt.y, r, r, aspect, fill); | 
|---|
| 483 | } | 
|---|
| 484 |  | 
|---|
| 485 | // | 
|---|
| 486 | //  ARC [STEP] x, y, r, start, end [, aspect[, color]] [COLOR color] | 
|---|
| 487 | // | 
|---|
| 488 | void cmd_arc() { | 
|---|
| 489 | int32_t color = dev_fgcolor; | 
|---|
| 490 | byte step = 0; | 
|---|
| 491 | int r; | 
|---|
| 492 | var_num_t as, ae, aspect = 1.0; | 
|---|
| 493 | byte code; | 
|---|
| 494 | ipt_t pt; | 
|---|
| 495 |  | 
|---|
| 496 | /* | 
|---|
| 497 | * [STEP] x, y | 
|---|
| 498 | */ | 
|---|
| 499 | code = code_peek(); | 
|---|
| 500 | if (code == kwSTEP) { | 
|---|
| 501 | code_skipnext(); | 
|---|
| 502 | step = 1; | 
|---|
| 503 | } | 
|---|
| 504 |  | 
|---|
| 505 | // xc,yc | 
|---|
| 506 | pt = par_getipt(); | 
|---|
| 507 | if (prog_error) | 
|---|
| 508 | return; | 
|---|
| 509 |  | 
|---|
| 510 | // r | 
|---|
| 511 | par_getcomma(); | 
|---|
| 512 | if (prog_error) | 
|---|
| 513 | return; | 
|---|
| 514 | r = par_getint(); | 
|---|
| 515 | if (prog_error) | 
|---|
| 516 | return; | 
|---|
| 517 |  | 
|---|
| 518 | // a.st. | 
|---|
| 519 | par_getcomma(); | 
|---|
| 520 | if (prog_error) | 
|---|
| 521 | return; | 
|---|
| 522 | as = par_getnum(); | 
|---|
| 523 | if (prog_error) | 
|---|
| 524 | return; | 
|---|
| 525 |  | 
|---|
| 526 | // a.end | 
|---|
| 527 | par_getcomma(); | 
|---|
| 528 | if (prog_error) | 
|---|
| 529 | return; | 
|---|
| 530 | ae = par_getnum(); | 
|---|
| 531 | if (prog_error) | 
|---|
| 532 | return; | 
|---|
| 533 |  | 
|---|
| 534 | if (step) | 
|---|
| 535 | (pt.x += gra_x, pt.y += gra_y); | 
|---|
| 536 |  | 
|---|
| 537 | // aspect | 
|---|
| 538 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 539 | par_getcomma(); | 
|---|
| 540 | if (prog_error) | 
|---|
| 541 | return; | 
|---|
| 542 | aspect = par_getnum(); | 
|---|
| 543 | if (prog_error) | 
|---|
| 544 | return; | 
|---|
| 545 |  | 
|---|
| 546 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 547 | par_getcomma(); | 
|---|
| 548 | if (prog_error) | 
|---|
| 549 | return; | 
|---|
| 550 | color = par_getint(); | 
|---|
| 551 | if (prog_error) | 
|---|
| 552 | return; | 
|---|
| 553 | } | 
|---|
| 554 | } | 
|---|
| 555 |  | 
|---|
| 556 | if (code_peek() == kwCOLOR) { | 
|---|
| 557 | code_skipnext(); | 
|---|
| 558 | color = par_getint(); | 
|---|
| 559 | if (prog_error) | 
|---|
| 560 | return; | 
|---|
| 561 | } | 
|---|
| 562 |  | 
|---|
| 563 | if (color != dev_fgcolor) { | 
|---|
| 564 | int32_t prev_color = dev_fgcolor; | 
|---|
| 565 |  | 
|---|
| 566 | dev_setcolor(color); | 
|---|
| 567 | dev_arc(pt.x, pt.y, r, as, ae, aspect); | 
|---|
| 568 | dev_setcolor(prev_color); | 
|---|
| 569 | } else { | 
|---|
| 570 | dev_arc(pt.x, pt.y, r, as, ae, aspect); | 
|---|
| 571 | } | 
|---|
| 572 | } | 
|---|
| 573 |  | 
|---|
| 574 | // | 
|---|
| 575 | //  PAINT [STEP] x, y [, fillcolor [, bordercolor]] | 
|---|
| 576 | // | 
|---|
| 577 | void cmd_paint() { | 
|---|
| 578 | int32_t prev_color = dev_fgcolor; | 
|---|
| 579 | int32_t color = dev_fgcolor; | 
|---|
| 580 | byte step = 0; | 
|---|
| 581 | int32_t fc = dev_fgcolor, bc = -1; | 
|---|
| 582 | byte code; | 
|---|
| 583 | ipt_t pt; | 
|---|
| 584 |  | 
|---|
| 585 | /* | 
|---|
| 586 | * [STEP] x, y | 
|---|
| 587 | */ | 
|---|
| 588 | code = code_peek(); | 
|---|
| 589 | if (code == kwSTEP) { | 
|---|
| 590 | code_skipnext(); | 
|---|
| 591 | step = 1; | 
|---|
| 592 | } | 
|---|
| 593 |  | 
|---|
| 594 | // xc,yc | 
|---|
| 595 | pt = par_getipt(); | 
|---|
| 596 | if (prog_error) { | 
|---|
| 597 | return; | 
|---|
| 598 | } | 
|---|
| 599 | if (step) { | 
|---|
| 600 | (pt.x += gra_x, pt.y += gra_y); | 
|---|
| 601 | } | 
|---|
| 602 | // fillcolor | 
|---|
| 603 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 604 | par_getcomma(); | 
|---|
| 605 | if (prog_error) { | 
|---|
| 606 | return; | 
|---|
| 607 | } | 
|---|
| 608 | fc = par_getint(); | 
|---|
| 609 | if (prog_error) { | 
|---|
| 610 | return; | 
|---|
| 611 | } | 
|---|
| 612 | } | 
|---|
| 613 |  | 
|---|
| 614 | // bordercolor | 
|---|
| 615 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 616 | par_getcomma(); | 
|---|
| 617 | if (prog_error) { | 
|---|
| 618 | return; | 
|---|
| 619 | } | 
|---|
| 620 | bc = par_getint(); | 
|---|
| 621 | if (prog_error) { | 
|---|
| 622 | return; | 
|---|
| 623 | } | 
|---|
| 624 | } | 
|---|
| 625 |  | 
|---|
| 626 | dev_setcolor(color); | 
|---|
| 627 | dev_ffill(pt.x, pt.y, fc, bc); | 
|---|
| 628 | dev_setcolor(prev_color); | 
|---|
| 629 | } | 
|---|
| 630 |  | 
|---|
| 631 | // | 
|---|
| 632 | char *draw_getval(const char *src, int *c) { | 
|---|
| 633 | char *p = (char *) src; | 
|---|
| 634 | char *dst, buf[64]; | 
|---|
| 635 |  | 
|---|
| 636 | dst = buf; | 
|---|
| 637 | p++; | 
|---|
| 638 | *c = 0; | 
|---|
| 639 | if (*p == '-') { | 
|---|
| 640 | *dst = '-'; | 
|---|
| 641 | dst++; | 
|---|
| 642 | p++; | 
|---|
| 643 | } | 
|---|
| 644 |  | 
|---|
| 645 | while (is_digit(*p)) { | 
|---|
| 646 | *dst++ = *p++; | 
|---|
| 647 | } | 
|---|
| 648 | *dst = '\0'; | 
|---|
| 649 |  | 
|---|
| 650 | *c = xstrtol(buf); | 
|---|
| 651 | return p; | 
|---|
| 652 | } | 
|---|
| 653 |  | 
|---|
| 654 | // | 
|---|
| 655 | //  DRAW "commands" | 
|---|
| 656 | // | 
|---|
| 657 | void cmd_draw() { | 
|---|
| 658 | register int draw = 1, update = 1; | 
|---|
| 659 | int x, y, r; | 
|---|
| 660 | int32_t prev_color = dev_fgcolor; | 
|---|
| 661 | char *p; | 
|---|
| 662 | var_t var; | 
|---|
| 663 |  | 
|---|
| 664 | par_getstr(&var); | 
|---|
| 665 | if (prog_error) { | 
|---|
| 666 | return; | 
|---|
| 667 | } | 
|---|
| 668 | p = var.v.p.ptr; | 
|---|
| 669 | while (*p) { | 
|---|
| 670 |  | 
|---|
| 671 | // 'N' command must affect only the next drawing command. | 
|---|
| 672 | update = 1; | 
|---|
| 673 | // Haraszti -- 'B' command must affect only the next drawing command. | 
|---|
| 674 | draw = 1; | 
|---|
| 675 |  | 
|---|
| 676 | // commands prefix | 
|---|
| 677 | while (strchr( "BbNn", *p)) { | 
|---|
| 678 | if (*p == 'B' || *p == 'b') { // do not draw | 
|---|
| 679 | draw = 0; | 
|---|
| 680 | p++; | 
|---|
| 681 | } else { | 
|---|
| 682 | draw = 1; | 
|---|
| 683 | } | 
|---|
| 684 | if (*p == 'N' || *p == 'n') { // do not update the position | 
|---|
| 685 | update = 0; | 
|---|
| 686 | p++; | 
|---|
| 687 | } else { | 
|---|
| 688 | update = 1; | 
|---|
| 689 | } | 
|---|
| 690 | } | 
|---|
| 691 |  | 
|---|
| 692 | // commands | 
|---|
| 693 | switch (*p) { | 
|---|
| 694 | case 'U': | 
|---|
| 695 | case 'u':                  // up | 
|---|
| 696 | p = draw_getval(p, &y); | 
|---|
| 697 | if (draw) { | 
|---|
| 698 | dev_line(gra_x, gra_y, gra_x, gra_y - y); | 
|---|
| 699 | } | 
|---|
| 700 | if (update) { | 
|---|
| 701 | gra_y -= y; | 
|---|
| 702 | } | 
|---|
| 703 | continue; | 
|---|
| 704 | case 'D': | 
|---|
| 705 | case 'd':                  // down | 
|---|
| 706 | p = draw_getval(p, &y); | 
|---|
| 707 | if (draw) { | 
|---|
| 708 | dev_line(gra_x, gra_y, gra_x, gra_y + y); | 
|---|
| 709 | } | 
|---|
| 710 | if (update) { | 
|---|
| 711 | gra_y += y; | 
|---|
| 712 | } | 
|---|
| 713 | continue; | 
|---|
| 714 | case 'L': | 
|---|
| 715 | case 'l':                  // left | 
|---|
| 716 | p = draw_getval(p, &x); | 
|---|
| 717 | if (draw) { | 
|---|
| 718 | dev_line(gra_x, gra_y, gra_x - x, gra_y); | 
|---|
| 719 | } | 
|---|
| 720 | if (update) { | 
|---|
| 721 | gra_x -= x; | 
|---|
| 722 | } | 
|---|
| 723 | continue; | 
|---|
| 724 | case 'R': | 
|---|
| 725 | case 'r':                  // right | 
|---|
| 726 | p = draw_getval(p, &x); | 
|---|
| 727 | if (draw) { | 
|---|
| 728 | dev_line(gra_x, gra_y, gra_x + x, gra_y); | 
|---|
| 729 | } | 
|---|
| 730 | if (update) { | 
|---|
| 731 | gra_x += x; | 
|---|
| 732 | } | 
|---|
| 733 | continue; | 
|---|
| 734 | case 'E': | 
|---|
| 735 | case 'e':                  // up & right | 
|---|
| 736 | p = draw_getval(p, &x); | 
|---|
| 737 | if (draw) { | 
|---|
| 738 | dev_line(gra_x, gra_y, gra_x + x, gra_y - x); | 
|---|
| 739 | } | 
|---|
| 740 | if (update) { | 
|---|
| 741 | gra_x += x; | 
|---|
| 742 | gra_y -= x; | 
|---|
| 743 | } | 
|---|
| 744 | continue; | 
|---|
| 745 | case 'F': | 
|---|
| 746 | case 'f':                  // down & right | 
|---|
| 747 | p = draw_getval(p, &x); | 
|---|
| 748 | if (draw) { | 
|---|
| 749 | dev_line(gra_x, gra_y, gra_x + x, gra_y + x); | 
|---|
| 750 | } | 
|---|
| 751 | if (update) { | 
|---|
| 752 | gra_x += x; | 
|---|
| 753 | gra_y += x; | 
|---|
| 754 | } | 
|---|
| 755 | continue; | 
|---|
| 756 | case 'G': | 
|---|
| 757 | case 'g':                  // down & left | 
|---|
| 758 | p = draw_getval(p, &x); | 
|---|
| 759 | if (draw) { | 
|---|
| 760 | dev_line(gra_x, gra_y, gra_x - x, gra_y + x); | 
|---|
| 761 | } | 
|---|
| 762 | if (update) { | 
|---|
| 763 | gra_x -= x; | 
|---|
| 764 | gra_y += x; | 
|---|
| 765 | } | 
|---|
| 766 | continue; | 
|---|
| 767 | case 'H': | 
|---|
| 768 | case 'h':                  // up & left | 
|---|
| 769 | p = draw_getval(p, &x); | 
|---|
| 770 | if (draw) { | 
|---|
| 771 | dev_line(gra_x, gra_y, gra_x - x, gra_y - x); | 
|---|
| 772 | } | 
|---|
| 773 | if (update) { | 
|---|
| 774 | gra_x -= x; | 
|---|
| 775 | gra_y -= x; | 
|---|
| 776 | } | 
|---|
| 777 | continue; | 
|---|
| 778 | case 'M': | 
|---|
| 779 | case 'm':                  // move to x, y | 
|---|
| 780 | if (*(p + 1) == '-') {    // relative | 
|---|
| 781 | r = -1; | 
|---|
| 782 | p++; | 
|---|
| 783 | } | 
|---|
| 784 | if (*(p + 1) == '+') {    // relative | 
|---|
| 785 | r = 1; | 
|---|
| 786 | p++; | 
|---|
| 787 | } else { | 
|---|
| 788 | r = 0;                  // absolute | 
|---|
| 789 | } | 
|---|
| 790 | p = draw_getval(p, &x); | 
|---|
| 791 | if (*p != ',') { | 
|---|
| 792 | rt_raise(ERR_DRAW_SEP); | 
|---|
| 793 | v_free(&var); | 
|---|
| 794 | return; | 
|---|
| 795 | } else { | 
|---|
| 796 | // Haraszti -- next pointer forward is an error because draw_getval | 
|---|
| 797 | // contain p++ too!!! | 
|---|
| 798 | // p ++; | 
|---|
| 799 | } | 
|---|
| 800 | p = draw_getval(p, &y); | 
|---|
| 801 |  | 
|---|
| 802 | if (r) { | 
|---|
| 803 | if (draw) | 
|---|
| 804 | dev_line(gra_x, gra_y, gra_x + x * r, gra_y + y * r); | 
|---|
| 805 | if (update) { | 
|---|
| 806 | gra_x += x * r; | 
|---|
| 807 | gra_y += x * r; | 
|---|
| 808 | } | 
|---|
| 809 | } else { | 
|---|
| 810 | if (draw) { | 
|---|
| 811 | dev_line(gra_x, gra_y, x, y); | 
|---|
| 812 | } | 
|---|
| 813 | if (update) { | 
|---|
| 814 | gra_x = x; | 
|---|
| 815 | gra_y = y; | 
|---|
| 816 | } | 
|---|
| 817 | } | 
|---|
| 818 | continue; | 
|---|
| 819 | case 'C': | 
|---|
| 820 | case 'c':                  // color | 
|---|
| 821 | p = draw_getval(p, &x); | 
|---|
| 822 | dev_setcolor(x); | 
|---|
| 823 | continue; | 
|---|
| 824 | // Haraszti -- next case filter out the spaces or tabs and semicolons | 
|---|
| 825 | // (GWBASIC compatibility) | 
|---|
| 826 | case ' ': | 
|---|
| 827 | case '\t': | 
|---|
| 828 | case ';': | 
|---|
| 829 | p++; | 
|---|
| 830 | continue; | 
|---|
| 831 | default: | 
|---|
| 832 | rt_raise(ERR_DRAW_CMD, *p); | 
|---|
| 833 | v_free(&var); | 
|---|
| 834 | return; | 
|---|
| 835 | } | 
|---|
| 836 | p++; | 
|---|
| 837 | } | 
|---|
| 838 |  | 
|---|
| 839 | dev_setcolor(prev_color); | 
|---|
| 840 | v_free(&var); | 
|---|
| 841 | } | 
|---|
| 842 |  | 
|---|
| 843 | // | 
|---|
| 844 | //  CHART chart-type, v() [, mark-type [, x1, y1, x2, y2]] | 
|---|
| 845 | // | 
|---|
| 846 | //  chart-type | 
|---|
| 847 | //      1 = line-chart | 
|---|
| 848 | //      2 = bar-chart | 
|---|
| 849 | // | 
|---|
| 850 | //  mark-type (bit-mask) | 
|---|
| 851 | //      0 = none | 
|---|
| 852 | //      1 = labels | 
|---|
| 853 | //      2 = ruler | 
|---|
| 854 | // | 
|---|
| 855 | void cmd_chart_fstr(var_num_t v, char *buf) { | 
|---|
| 856 | if (fabsl(v) >= 10E+9) { | 
|---|
| 857 | ftostr(v / 1E+9, buf); | 
|---|
| 858 | if (buf[3] == '.') { | 
|---|
| 859 | buf[3] = '\0'; | 
|---|
| 860 | } else { | 
|---|
| 861 | buf[4] = '\0'; | 
|---|
| 862 | } | 
|---|
| 863 | strcat(buf, "G"); | 
|---|
| 864 | } else if (fabsl(v) >= 10E+6) { | 
|---|
| 865 | ftostr(v / 1E+6, buf); | 
|---|
| 866 | if (buf[3] == '.') { | 
|---|
| 867 | buf[3] = '\0'; | 
|---|
| 868 | } else { | 
|---|
| 869 | buf[4] = '\0'; | 
|---|
| 870 | } | 
|---|
| 871 | strcat(buf, "M"); | 
|---|
| 872 | } else if (fabsl(v) >= 10E+3) { | 
|---|
| 873 | ftostr(v / 1E+3, buf); | 
|---|
| 874 | if (buf[3] == '.') { | 
|---|
| 875 | buf[3] = '\0'; | 
|---|
| 876 | } else { | 
|---|
| 877 | buf[4] = '\0'; | 
|---|
| 878 | } | 
|---|
| 879 | strcat(buf, "K"); | 
|---|
| 880 | } else { | 
|---|
| 881 | ftostr(v, buf); | 
|---|
| 882 | buf[5] = '\0'; | 
|---|
| 883 | } | 
|---|
| 884 | } | 
|---|
| 885 |  | 
|---|
| 886 | /* | 
|---|
| 887 | * draw a chart | 
|---|
| 888 | * | 
|---|
| 889 | * x1,y1-x2,y2 = the area to draw | 
|---|
| 890 | * vals = the values | 
|---|
| 891 | * count = the number of the values | 
|---|
| 892 | * xvals, xcount = for ruler the xvalues (use NULL for default) | 
|---|
| 893 | * chart = chart type (1=line chart, 0=bar chart, 5=points) | 
|---|
| 894 | * marks = marks type (2 & ruler, 1 & marks) | 
|---|
| 895 | */ | 
|---|
| 896 | void chart_draw(int x1, int y1, int x2, int y2, var_num_t *vals, int count, | 
|---|
| 897 | var_num_t *xvals, int xcount, int chart, int marks) { | 
|---|
| 898 | var_num_t lx, ly; | 
|---|
| 899 | char buf[32]; | 
|---|
| 900 | int32_t color = 0; | 
|---|
| 901 | int rx1 = x1; | 
|---|
| 902 |  | 
|---|
| 903 | // ready | 
|---|
| 904 | dev_settextcolor(0, 15); | 
|---|
| 905 | int *pts = (int *) malloc(sizeof(int) * count * 2); | 
|---|
| 906 |  | 
|---|
| 907 | if (marks & 0x2) { | 
|---|
| 908 | // ruler | 
|---|
| 909 | x1 += dev_textwidth( "00000") + 1; | 
|---|
| 910 | y2 -= (dev_textheight( "0") + 1); | 
|---|
| 911 | } | 
|---|
| 912 |  | 
|---|
| 913 | if (marks & 0x1) { | 
|---|
| 914 | if (chart == 1) { | 
|---|
| 915 | // line | 
|---|
| 916 | x1 += 2; | 
|---|
| 917 | x2 -= 2; | 
|---|
| 918 | y1 += 2; | 
|---|
| 919 | y2 -= 2; | 
|---|
| 920 | } | 
|---|
| 921 | } | 
|---|
| 922 |  | 
|---|
| 923 | int dx = (x2 - x1); | 
|---|
| 924 | int dy = (y2 - y1); | 
|---|
| 925 |  | 
|---|
| 926 | // limits | 
|---|
| 927 | var_num_t vmin = vals[0]; | 
|---|
| 928 | var_num_t vmax = vals[0]; | 
|---|
| 929 | for (int i = 1; i < count; i++) { | 
|---|
| 930 | if (vmin > vals[i]) { | 
|---|
| 931 | vmin = vals[i]; | 
|---|
| 932 | } | 
|---|
| 933 | if (vmax < vals[i]) { | 
|---|
| 934 | vmax = vals[i]; | 
|---|
| 935 | } | 
|---|
| 936 | } | 
|---|
| 937 |  | 
|---|
| 938 | if (chart == 1) { | 
|---|
| 939 | // line-chart | 
|---|
| 940 | lx = ((var_num_t) dx) / (var_num_t) (count - 1); | 
|---|
| 941 | } else { | 
|---|
| 942 | lx = ((var_num_t) dx) / (var_num_t) count; | 
|---|
| 943 | } | 
|---|
| 944 | ly = ((var_num_t) dy) / (vmax - vmin); | 
|---|
| 945 |  | 
|---|
| 946 | // calc points | 
|---|
| 947 | for (int i = 0; i < count; i++) { | 
|---|
| 948 | int x = x1 + i * lx; | 
|---|
| 949 | int y = y1 + (dy - ((vals[i] - vmin) * ly)); | 
|---|
| 950 | pts[i * 2] = x > 0 ? x : 0; | 
|---|
| 951 | pts[i * 2 + 1] = y > 0 ? y : 0; | 
|---|
| 952 | } | 
|---|
| 953 |  | 
|---|
| 954 | // draw ruler | 
|---|
| 955 | if (marks & 0x2) { | 
|---|
| 956 | // vertical | 
|---|
| 957 | int fh = dev_textheight( "0"); | 
|---|
| 958 | int n = dy / (fh * 1.5); | 
|---|
| 959 |  | 
|---|
| 960 | if ((n - 1) > 0) { | 
|---|
| 961 | for (int i = 0; i <= n; i++) { | 
|---|
| 962 | var_num_t v; | 
|---|
| 963 | if (i == 0) { | 
|---|
| 964 | v = vmin; | 
|---|
| 965 | } | 
|---|
| 966 | else if (i == n) { | 
|---|
| 967 | v = vmax; | 
|---|
| 968 | } else { | 
|---|
| 969 | v = vmin + (((var_num_t) i + 1) * ((vmax - vmin) / (var_num_t) (n + 1))); | 
|---|
| 970 | } | 
|---|
| 971 | cmd_chart_fstr(v, buf); | 
|---|
| 972 |  | 
|---|
| 973 | int y = y1 + (dy - ((v - vmin) * ly)); | 
|---|
| 974 | if (i != 0) { | 
|---|
| 975 | dev_setxy(rx1 + 1, y + 1, 0); | 
|---|
| 976 | } else { | 
|---|
| 977 | dev_setxy(rx1 + 1, y - fh, 0); | 
|---|
| 978 | } | 
|---|
| 979 | dev_print(buf); | 
|---|
| 980 | dev_line(x1 - 4, y, x1, y); | 
|---|
| 981 | } | 
|---|
| 982 | } | 
|---|
| 983 |  | 
|---|
| 984 | // horizontal | 
|---|
| 985 | int fw = dev_textwidth( "000"); | 
|---|
| 986 | n = -1; | 
|---|
| 987 | if (count <= 24) { | 
|---|
| 988 | if (count * (fw * 1.34) < dx) { | 
|---|
| 989 | n = count; | 
|---|
| 990 | } | 
|---|
| 991 | } | 
|---|
| 992 |  | 
|---|
| 993 | if (n == -1) { | 
|---|
| 994 | n = dx / (fw * 1.5); | 
|---|
| 995 | } | 
|---|
| 996 | if ((n - 1) > 0) { | 
|---|
| 997 | for (int i = 0; i < n; i++) { | 
|---|
| 998 | var_num_t v; | 
|---|
| 999 | if (i == 0) { | 
|---|
| 1000 | v = 0; | 
|---|
| 1001 | } else { | 
|---|
| 1002 | v = i * ((var_num_t) count / (var_num_t) n); | 
|---|
| 1003 | } | 
|---|
| 1004 | if (xvals) { | 
|---|
| 1005 | // I have xvals | 
|---|
| 1006 | var_num_t x; | 
|---|
| 1007 | var_num_t xmin = xvals[0]; | 
|---|
| 1008 | var_num_t xmax = xvals[xcount - 1]; | 
|---|
| 1009 | var_num_t dx = xmax - xmin; | 
|---|
| 1010 | if (i == 0) { | 
|---|
| 1011 | x = xmin; | 
|---|
| 1012 | } else if (i == n) { | 
|---|
| 1013 | x = xmax; | 
|---|
| 1014 | } else { | 
|---|
| 1015 | x = xmin + ((dx / n) * i); | 
|---|
| 1016 | } | 
|---|
| 1017 | ftostr(x, buf); | 
|---|
| 1018 | } else { | 
|---|
| 1019 | // i don't have xvals | 
|---|
| 1020 | ftostr(i + 1, buf); | 
|---|
| 1021 | } | 
|---|
| 1022 |  | 
|---|
| 1023 | buf[3] = '\0'; | 
|---|
| 1024 | fw = dev_textwidth(buf); | 
|---|
| 1025 |  | 
|---|
| 1026 | int x = x1 + v * lx; | 
|---|
| 1027 | if (chart == 1 || chart == 5) { | 
|---|
| 1028 | dev_setxy(x - fw, y2 + 1, 0); | 
|---|
| 1029 | } else { | 
|---|
| 1030 | if (x + fw + 1 < x2) { | 
|---|
| 1031 | dev_setxy(x + 1, y2 + 1, 0); | 
|---|
| 1032 | } | 
|---|
| 1033 | } | 
|---|
| 1034 |  | 
|---|
| 1035 | dev_print(buf); | 
|---|
| 1036 | dev_line(x, y2, x, y2 + 4); | 
|---|
| 1037 | } | 
|---|
| 1038 | } | 
|---|
| 1039 |  | 
|---|
| 1040 | dev_line(x1, y1, x1, y2); | 
|---|
| 1041 | dev_line(x1, y2, x2, y2); | 
|---|
| 1042 |  | 
|---|
| 1043 | x1++; | 
|---|
| 1044 | y2--; | 
|---|
| 1045 | dx = (x2 - x1); | 
|---|
| 1046 | dy = (y2 - y1); | 
|---|
| 1047 | } | 
|---|
| 1048 |  | 
|---|
| 1049 | // draw | 
|---|
| 1050 | switch (chart) { | 
|---|
| 1051 | case 1: | 
|---|
| 1052 | case 5: | 
|---|
| 1053 | // line chart | 
|---|
| 1054 | // points | 
|---|
| 1055 | if (chart == 5) { | 
|---|
| 1056 | for (int i = 0; i < count; i++) { | 
|---|
| 1057 | dev_setpixel(pts[i * 2], pts[i * 2 + 1]); | 
|---|
| 1058 | } | 
|---|
| 1059 | } else { | 
|---|
| 1060 | for (int i = 1; i < count; i++) { | 
|---|
| 1061 | dev_line(pts[(i - 1) * 2], pts[(i - 1) * 2 + 1], pts[i * 2], pts[i * 2 + 1]); | 
|---|
| 1062 | } | 
|---|
| 1063 | } | 
|---|
| 1064 |  | 
|---|
| 1065 | // draw marks | 
|---|
| 1066 | if (marks & 0x1) { | 
|---|
| 1067 | for (int i = 0; i < count; i++) { | 
|---|
| 1068 | cmd_chart_fstr(vals[i], buf); | 
|---|
| 1069 |  | 
|---|
| 1070 | int fw = dev_textwidth(buf); | 
|---|
| 1071 | int fh = dev_textheight(buf); | 
|---|
| 1072 | int mx = pts[i * 2] - fw / 2; | 
|---|
| 1073 | int my = pts[i * 2 + 1]; | 
|---|
| 1074 |  | 
|---|
| 1075 | if (my > (y1 + (y2 - y1) / 2)) { | 
|---|
| 1076 | my -= fh; | 
|---|
| 1077 | } | 
|---|
| 1078 | if (mx <= x1) { | 
|---|
| 1079 | mx = x1 + 1; | 
|---|
| 1080 | } | 
|---|
| 1081 | if (mx + fw >= x2) { | 
|---|
| 1082 | mx = x2 - fw; | 
|---|
| 1083 | } | 
|---|
| 1084 | dev_setxy(mx, my, 0); | 
|---|
| 1085 | dev_print(buf); | 
|---|
| 1086 | dev_rect(pts[i * 2] - 2, pts[i * 2 + 1] - 2, | 
|---|
| 1087 | pts[i * 2] + 2, pts[i * 2 + 1] + 2, 1); | 
|---|
| 1088 | } | 
|---|
| 1089 | } | 
|---|
| 1090 | break; | 
|---|
| 1091 |  | 
|---|
| 1092 | case 2: | 
|---|
| 1093 | // bar chart | 
|---|
| 1094 | // draw rect | 
|---|
| 1095 | color = 0; | 
|---|
| 1096 | for (int i = 1; i < count; i++) { | 
|---|
| 1097 | if (os_color_depth > 2) { | 
|---|
| 1098 | dev_setcolor(color); | 
|---|
| 1099 | color++; | 
|---|
| 1100 | if (color >= 15) { | 
|---|
| 1101 | color = 0; | 
|---|
| 1102 | } | 
|---|
| 1103 | } | 
|---|
| 1104 | dev_rect(pts[(i - 1) * 2], pts[(i - 1) * 2 + 1], pts[i * 2] - 2, y2, 1); | 
|---|
| 1105 | } | 
|---|
| 1106 |  | 
|---|
| 1107 | if (os_color_depth > 2) { | 
|---|
| 1108 | dev_setcolor(color); | 
|---|
| 1109 | } | 
|---|
| 1110 | dev_rect(pts[(count - 1) * 2], pts[(count - 1) * 2 + 1], | 
|---|
| 1111 | pts[(count - 1) * 2] + lx - 1, y2, 1); | 
|---|
| 1112 |  | 
|---|
| 1113 | // draw marks | 
|---|
| 1114 | if (marks & 0x1) { | 
|---|
| 1115 | color = 0; | 
|---|
| 1116 | for (int i = 0; i < count; i++) { | 
|---|
| 1117 | cmd_chart_fstr(vals[i], buf); | 
|---|
| 1118 |  | 
|---|
| 1119 | int fw = dev_textwidth(buf); | 
|---|
| 1120 | int fh = dev_textheight(buf); | 
|---|
| 1121 | int mx = pts[i * 2] + lx / 2 - fw / 2; | 
|---|
| 1122 | int my = pts[i * 2 + 1]; | 
|---|
| 1123 |  | 
|---|
| 1124 | if (os_color_depth > 2) { | 
|---|
| 1125 | if (my - fh >= y1) { | 
|---|
| 1126 | dev_settextcolor(0, 15); | 
|---|
| 1127 | } else { | 
|---|
| 1128 | if (color >= 7 && color != 8) { | 
|---|
| 1129 | dev_settextcolor(0, color); | 
|---|
| 1130 | } else { | 
|---|
| 1131 | dev_settextcolor(15, color); | 
|---|
| 1132 | } | 
|---|
| 1133 | } | 
|---|
| 1134 |  | 
|---|
| 1135 | color++; | 
|---|
| 1136 | if (color >= 15) { | 
|---|
| 1137 | color = 0; | 
|---|
| 1138 | } | 
|---|
| 1139 | } | 
|---|
| 1140 |  | 
|---|
| 1141 | if (my - fh >= y1) { | 
|---|
| 1142 | my -= fh; | 
|---|
| 1143 | } | 
|---|
| 1144 | if (mx <= x1) { | 
|---|
| 1145 | mx = x1 + 1; | 
|---|
| 1146 | } | 
|---|
| 1147 | if (mx + fw >= x2) { | 
|---|
| 1148 | mx = x2 - fw; | 
|---|
| 1149 | } | 
|---|
| 1150 | dev_setxy(mx, my, 0); | 
|---|
| 1151 | dev_print(buf); | 
|---|
| 1152 | } | 
|---|
| 1153 | } | 
|---|
| 1154 | break; | 
|---|
| 1155 | }; | 
|---|
| 1156 |  | 
|---|
| 1157 | free(pts); | 
|---|
| 1158 | } | 
|---|
| 1159 |  | 
|---|
| 1160 | // | 
|---|
| 1161 | //  CHART | 
|---|
| 1162 | // | 
|---|
| 1163 | void cmd_chart() { | 
|---|
| 1164 | int32_t prev_fgcolor = dev_fgcolor; | 
|---|
| 1165 | int32_t prev_bgcolor = dev_bgcolor; | 
|---|
| 1166 | int x1 = 0; | 
|---|
| 1167 | int y1 = 0; | 
|---|
| 1168 | int x2 = os_graf_mx; | 
|---|
| 1169 | int y2 = os_graf_my; | 
|---|
| 1170 |  | 
|---|
| 1171 | // chart type | 
|---|
| 1172 | int chart = par_getint(); IF_PROG_ERR_RTN; | 
|---|
| 1173 | par_getcomma();           IF_PROG_ERR_RTN; | 
|---|
| 1174 |  | 
|---|
| 1175 | // array | 
|---|
| 1176 | var_t *var_p = par_getvarray(); IF_PROG_ERR_RTN; | 
|---|
| 1177 | if (!var_p || var_p->type != V_ARRAY) { | 
|---|
| 1178 | err_varisnotarray(); | 
|---|
| 1179 | return; | 
|---|
| 1180 | } | 
|---|
| 1181 |  | 
|---|
| 1182 | // optional labels-flag | 
|---|
| 1183 | int marks; | 
|---|
| 1184 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 1185 | par_getcomma();         IF_PROG_ERR_RTN; | 
|---|
| 1186 | marks = par_getint();   IF_PROG_ERR_RTN; | 
|---|
| 1187 |  | 
|---|
| 1188 | // optional x1,y1,x2,y2 | 
|---|
| 1189 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 1190 | par_getcomma();       IF_PROG_ERR_RTN; | 
|---|
| 1191 | x1 = par_getint();    IF_PROG_ERR_RTN; | 
|---|
| 1192 | par_getcomma();       IF_PROG_ERR_RTN; | 
|---|
| 1193 | y1 = par_getint();    IF_PROG_ERR_RTN; | 
|---|
| 1194 | par_getcomma();       IF_PROG_ERR_RTN; | 
|---|
| 1195 | x2 = par_getint();    IF_PROG_ERR_RTN; | 
|---|
| 1196 | par_getcomma();       IF_PROG_ERR_RTN; | 
|---|
| 1197 | y2 = par_getint();    IF_PROG_ERR_RTN; | 
|---|
| 1198 | } | 
|---|
| 1199 | } else { | 
|---|
| 1200 | marks = 0; | 
|---|
| 1201 | } | 
|---|
| 1202 |  | 
|---|
| 1203 | // get array's values | 
|---|
| 1204 | int count = v_asize(var_p); | 
|---|
| 1205 | var_num_t *vals = (var_num_t *) malloc(sizeof(var_num_t) * count); | 
|---|
| 1206 | for (int i = 0; i < count; i++) { | 
|---|
| 1207 | var_t *elem_p = v_elem(var_p, i); | 
|---|
| 1208 | if (prog_error) { | 
|---|
| 1209 | free(vals); | 
|---|
| 1210 | return; | 
|---|
| 1211 | } | 
|---|
| 1212 | switch (elem_p->type) { | 
|---|
| 1213 | case V_INT: | 
|---|
| 1214 | vals[i] = elem_p->v.i; | 
|---|
| 1215 | break; | 
|---|
| 1216 | case V_NUM: | 
|---|
| 1217 | vals[i] = elem_p->v.n; | 
|---|
| 1218 | break; | 
|---|
| 1219 | case V_STR: | 
|---|
| 1220 | vals[i] = v_getreal(elem_p); | 
|---|
| 1221 | break; | 
|---|
| 1222 | default: | 
|---|
| 1223 | err_typemismatch(); | 
|---|
| 1224 | free(vals); | 
|---|
| 1225 | return; | 
|---|
| 1226 | } | 
|---|
| 1227 | } | 
|---|
| 1228 |  | 
|---|
| 1229 | chart_draw(x1, y1, x2, y2, vals, count, NULL, 0, chart, marks); | 
|---|
| 1230 |  | 
|---|
| 1231 | free(vals); | 
|---|
| 1232 | dev_settextcolor(prev_fgcolor, prev_bgcolor); | 
|---|
| 1233 | } | 
|---|
| 1234 |  | 
|---|
| 1235 | var_t *par_getm3() { | 
|---|
| 1236 | // array | 
|---|
| 1237 | var_t *vp = par_getvarray(); | 
|---|
| 1238 | if (prog_error) { | 
|---|
| 1239 | return NULL; | 
|---|
| 1240 | } | 
|---|
| 1241 | if (vp == NULL || vp->type != V_ARRAY || v_asize(vp) != 9) { | 
|---|
| 1242 | err_typemismatch(); | 
|---|
| 1243 | return NULL; | 
|---|
| 1244 | } | 
|---|
| 1245 | return vp; | 
|---|
| 1246 | } | 
|---|
| 1247 |  | 
|---|
| 1248 | void m3combine(var_t *m, var_num_t nm[3][3]) { | 
|---|
| 1249 | var_num_t om[3][3]; | 
|---|
| 1250 | int i, j; | 
|---|
| 1251 | var_t *e; | 
|---|
| 1252 |  | 
|---|
| 1253 | // copy m to om | 
|---|
| 1254 | for (i = 0; i < 3; i++) { | 
|---|
| 1255 | for (j = 0; j < 3; j++) { | 
|---|
| 1256 | e = v_elem(m, (i * 3 + j)); | 
|---|
| 1257 | if (e->type == V_NUM) { | 
|---|
| 1258 | om[i][j] = e->v.n; | 
|---|
| 1259 | } else if (e->type == V_INT) { | 
|---|
| 1260 | om[i][j] = e->v.i; | 
|---|
| 1261 | } else { | 
|---|
| 1262 | om[i][j] = v_getval(e); | 
|---|
| 1263 | } | 
|---|
| 1264 | } | 
|---|
| 1265 | } | 
|---|
| 1266 |  | 
|---|
| 1267 | // combine | 
|---|
| 1268 | for (i = 0; i < 3; i++) { | 
|---|
| 1269 | for (j = 0; j < 3; j++) { | 
|---|
| 1270 | e = v_elem(m, (i * 3 + j)); | 
|---|
| 1271 | if (e->type != V_NUM) { | 
|---|
| 1272 | v_free(e); | 
|---|
| 1273 | } | 
|---|
| 1274 | e->type = V_NUM; | 
|---|
| 1275 | e->v.n = nm[i][0] * om[0][j] + nm[i][1] * om[1][j] + nm[i][2] * om[2][j]; | 
|---|
| 1276 | } | 
|---|
| 1277 | } | 
|---|
| 1278 |  | 
|---|
| 1279 | } | 
|---|
| 1280 |  | 
|---|
| 1281 | // | 
|---|
| 1282 | void m3ident(var_num_t m[3][3]) { | 
|---|
| 1283 | int i, j; | 
|---|
| 1284 |  | 
|---|
| 1285 | for (i = 0; i < 3; i++) { | 
|---|
| 1286 | for (j = 0; j < 3; j++) { | 
|---|
| 1287 | m[i][j] = (i == j) ? 1.0 : 0.0; | 
|---|
| 1288 | } | 
|---|
| 1289 | } | 
|---|
| 1290 | } | 
|---|
| 1291 |  | 
|---|
| 1292 | // | 
|---|
| 1293 | //  M3IDENT BYREF m3x3 | 
|---|
| 1294 | // | 
|---|
| 1295 | void cmd_m3ident() { | 
|---|
| 1296 | var_t *m, *e; | 
|---|
| 1297 | int i, j; | 
|---|
| 1298 |  | 
|---|
| 1299 | m = par_getm3(); | 
|---|
| 1300 | if (prog_error) { | 
|---|
| 1301 | return; | 
|---|
| 1302 | } | 
|---|
| 1303 | for (i = 0; i < 3; i++) { | 
|---|
| 1304 | for (j = 0; j < 3; j++) { | 
|---|
| 1305 | e = v_elem(m, (i * 3 + j)); | 
|---|
| 1306 | v_init(e); | 
|---|
| 1307 | e->type = V_NUM; | 
|---|
| 1308 | e->v.n = (i == j) ? 1.0 : 0.0; | 
|---|
| 1309 | } | 
|---|
| 1310 | } | 
|---|
| 1311 | } | 
|---|
| 1312 |  | 
|---|
| 1313 | // | 
|---|
| 1314 | //  M3ROTATE BYREF m3x3, angle[, x, y] | 
|---|
| 1315 | // | 
|---|
| 1316 | void cmd_m3rotate() { | 
|---|
| 1317 | var_t *m; | 
|---|
| 1318 | var_num_t angle, x = 0, y = 0, c, s; | 
|---|
| 1319 | var_num_t matrix[3][3]; | 
|---|
| 1320 |  | 
|---|
| 1321 | m = par_getm3(); | 
|---|
| 1322 | if (prog_error) { | 
|---|
| 1323 | return; | 
|---|
| 1324 | } | 
|---|
| 1325 | par_getcomma(); | 
|---|
| 1326 | if (prog_error) { | 
|---|
| 1327 | return; | 
|---|
| 1328 | } | 
|---|
| 1329 | angle = par_getnum(); | 
|---|
| 1330 | if (prog_error) { | 
|---|
| 1331 | return; | 
|---|
| 1332 | } | 
|---|
| 1333 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 1334 | par_getcomma(); | 
|---|
| 1335 | if (prog_error) | 
|---|
| 1336 | return; | 
|---|
| 1337 | x = par_getnum(); | 
|---|
| 1338 | if (prog_error) | 
|---|
| 1339 | return; | 
|---|
| 1340 | par_getcomma(); | 
|---|
| 1341 | if (prog_error) | 
|---|
| 1342 | return; | 
|---|
| 1343 | y = par_getnum(); | 
|---|
| 1344 | if (prog_error) { | 
|---|
| 1345 | return; | 
|---|
| 1346 | } | 
|---|
| 1347 | } | 
|---|
| 1348 |  | 
|---|
| 1349 | c = cos(angle); | 
|---|
| 1350 | s = sin(angle); | 
|---|
| 1351 |  | 
|---|
| 1352 | m3ident(matrix); | 
|---|
| 1353 | matrix[0][0] = c; | 
|---|
| 1354 | matrix[0][1] = s; | 
|---|
| 1355 | matrix[1][0] = -s; | 
|---|
| 1356 | matrix[1][1] = c; | 
|---|
| 1357 | matrix[2][0] = (1.0 - c) * x + (s * y); | 
|---|
| 1358 | matrix[2][1] = (1.0 - c) * y - (s * x); | 
|---|
| 1359 | m3combine(m, matrix); | 
|---|
| 1360 | } | 
|---|
| 1361 |  | 
|---|
| 1362 | // | 
|---|
| 1363 | //  M3SCALE BYREF m3x3, x, y, fx, fy | 
|---|
| 1364 | // | 
|---|
| 1365 | void cmd_m3scale() { | 
|---|
| 1366 | var_t *m; | 
|---|
| 1367 | var_num_t x, y, fx, fy; | 
|---|
| 1368 | var_num_t matrix[3][3]; | 
|---|
| 1369 |  | 
|---|
| 1370 | m = par_getm3(); | 
|---|
| 1371 | if (prog_error) | 
|---|
| 1372 | return; | 
|---|
| 1373 | par_getcomma(); | 
|---|
| 1374 | if (prog_error) | 
|---|
| 1375 | return; | 
|---|
| 1376 | x = par_getnum(); | 
|---|
| 1377 | if (prog_error) | 
|---|
| 1378 | return; | 
|---|
| 1379 | par_getcomma(); | 
|---|
| 1380 | if (prog_error) | 
|---|
| 1381 | return; | 
|---|
| 1382 | y = par_getnum(); | 
|---|
| 1383 | if (prog_error) | 
|---|
| 1384 | return; | 
|---|
| 1385 | par_getcomma(); | 
|---|
| 1386 | if (prog_error) | 
|---|
| 1387 | return; | 
|---|
| 1388 | fx = par_getnum(); | 
|---|
| 1389 | if (prog_error) | 
|---|
| 1390 | return; | 
|---|
| 1391 | par_getcomma(); | 
|---|
| 1392 | if (prog_error) | 
|---|
| 1393 | return; | 
|---|
| 1394 | fy = par_getnum(); | 
|---|
| 1395 | if (prog_error) | 
|---|
| 1396 | return; | 
|---|
| 1397 |  | 
|---|
| 1398 | m3ident(matrix); | 
|---|
| 1399 | matrix[0][0] = fx; | 
|---|
| 1400 | matrix[1][1] = fy; | 
|---|
| 1401 | matrix[2][0] = (1.0 - fx) * x; | 
|---|
| 1402 | matrix[2][1] = (1.0 - fy) * y; | 
|---|
| 1403 | m3combine(m, matrix); | 
|---|
| 1404 | } | 
|---|
| 1405 |  | 
|---|
| 1406 | // | 
|---|
| 1407 | //  M3TRANS BYREF m3x3, x, y | 
|---|
| 1408 | // | 
|---|
| 1409 | void cmd_m3translate() { | 
|---|
| 1410 | var_t *m; | 
|---|
| 1411 | var_num_t x, y; | 
|---|
| 1412 | var_num_t matrix[3][3]; | 
|---|
| 1413 |  | 
|---|
| 1414 | m = par_getm3(); | 
|---|
| 1415 | if (prog_error) | 
|---|
| 1416 | return; | 
|---|
| 1417 | par_getcomma(); | 
|---|
| 1418 | if (prog_error) | 
|---|
| 1419 | return; | 
|---|
| 1420 | x = par_getnum(); | 
|---|
| 1421 | if (prog_error) | 
|---|
| 1422 | return; | 
|---|
| 1423 | par_getcomma(); | 
|---|
| 1424 | if (prog_error) | 
|---|
| 1425 | return; | 
|---|
| 1426 | y = par_getnum(); | 
|---|
| 1427 | if (prog_error) | 
|---|
| 1428 | return; | 
|---|
| 1429 |  | 
|---|
| 1430 | m3ident(matrix); | 
|---|
| 1431 | matrix[2][0] = x; | 
|---|
| 1432 | matrix[2][1] = y; | 
|---|
| 1433 | m3combine(m, matrix); | 
|---|
| 1434 | } | 
|---|
| 1435 |  | 
|---|
| 1436 | // | 
|---|
| 1437 | //  M3APPLY m3x3, BYREF poly | 
|---|
| 1438 | // | 
|---|
| 1439 | void cmd_m3apply() { | 
|---|
| 1440 | var_t *m, *p, *e; | 
|---|
| 1441 | var_num_t om[3][3], x, y; | 
|---|
| 1442 | int i, j, count; | 
|---|
| 1443 |  | 
|---|
| 1444 | m = par_getm3(); | 
|---|
| 1445 | if (prog_error) | 
|---|
| 1446 | return; | 
|---|
| 1447 | par_getcomma(); | 
|---|
| 1448 | if (prog_error) | 
|---|
| 1449 | return; | 
|---|
| 1450 | p = par_getvarray(); | 
|---|
| 1451 | if (prog_error) | 
|---|
| 1452 | return; | 
|---|
| 1453 | count = v_asize(p); | 
|---|
| 1454 |  | 
|---|
| 1455 | // copy m to om | 
|---|
| 1456 | for (i = 0; i < 3; i++) { | 
|---|
| 1457 | for (j = 0; j < 3; j++) { | 
|---|
| 1458 | e = v_elem(m, i * 3 + j); | 
|---|
| 1459 | om[i][j] = v_getreal(e); | 
|---|
| 1460 | } | 
|---|
| 1461 | } | 
|---|
| 1462 |  | 
|---|
| 1463 | // apply | 
|---|
| 1464 | e = v_elem(p, 0); | 
|---|
| 1465 | if (e->type != V_ARRAY) { | 
|---|
| 1466 | int o; | 
|---|
| 1467 |  | 
|---|
| 1468 | count = (v_asize(p) >> 1); | 
|---|
| 1469 | for (i = 0; i < count; i++) { | 
|---|
| 1470 | o = i << 1; | 
|---|
| 1471 | x = v_getreal(v_elem(p, o)); | 
|---|
| 1472 | y = v_getreal(v_elem(p, o + 1)); | 
|---|
| 1473 | v_setreal(v_elem(p, o), x * om[0][0] + y * om[1][0] + om[2][0]); | 
|---|
| 1474 | v_setreal(v_elem(p, o + 1), x * om[0][1] + y * om[1][1] + om[2][1]); | 
|---|
| 1475 | } | 
|---|
| 1476 | } else { | 
|---|
| 1477 | for (i = 0; i < count; i++) { | 
|---|
| 1478 | e = v_elem(p, i); | 
|---|
| 1479 |  | 
|---|
| 1480 | if (e->type != V_ARRAY) | 
|---|
| 1481 | err_parsepoly(i, 10); | 
|---|
| 1482 | else if ((v_asize(e) % 2) != 0) | 
|---|
| 1483 | err_parsepoly(i, 11); | 
|---|
| 1484 |  | 
|---|
| 1485 | if (prog_error) | 
|---|
| 1486 | break; | 
|---|
| 1487 |  | 
|---|
| 1488 | x = v_getreal(v_elem(e, 0)); | 
|---|
| 1489 | y = v_getreal(v_elem(e, 1)); | 
|---|
| 1490 | v_setreal(v_elem(e, 0), x * om[0][0] + y * om[1][0] + om[2][0]); | 
|---|
| 1491 | v_setreal(v_elem(e, 1), x * om[0][1] + y * om[1][1] + om[2][1]); | 
|---|
| 1492 | } | 
|---|
| 1493 | } | 
|---|
| 1494 | } | 
|---|
| 1495 |  | 
|---|
| 1496 | // | 
|---|
| 1497 | // INTERSECT a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y, BYREF type, BYREF r.x, BYREF r.y | 
|---|
| 1498 | // | 
|---|
| 1499 | void cmd_intersect() { | 
|---|
| 1500 | var_num_t a, b, c, s; | 
|---|
| 1501 | pt_t A, B, C, D, R; | 
|---|
| 1502 | var_t *type, *vrx, *vry = NULL; | 
|---|
| 1503 | byte style = 0; | 
|---|
| 1504 |  | 
|---|
| 1505 | // parameters | 
|---|
| 1506 | A = par_getpt(); | 
|---|
| 1507 | if (prog_error) | 
|---|
| 1508 | return; | 
|---|
| 1509 | par_getcomma(); | 
|---|
| 1510 | if (prog_error) | 
|---|
| 1511 | return; | 
|---|
| 1512 | B = par_getpt(); | 
|---|
| 1513 | if (prog_error) | 
|---|
| 1514 | return; | 
|---|
| 1515 | par_getcomma(); | 
|---|
| 1516 | if (prog_error) | 
|---|
| 1517 | return; | 
|---|
| 1518 | C = par_getpt(); | 
|---|
| 1519 | if (prog_error) | 
|---|
| 1520 | return; | 
|---|
| 1521 | par_getcomma(); | 
|---|
| 1522 | if (prog_error) | 
|---|
| 1523 | return; | 
|---|
| 1524 | D = par_getpt(); | 
|---|
| 1525 | if (prog_error) | 
|---|
| 1526 | return; | 
|---|
| 1527 | par_getcomma(); | 
|---|
| 1528 | if (prog_error) | 
|---|
| 1529 | return; | 
|---|
| 1530 |  | 
|---|
| 1531 | type = par_getvar_ptr(); | 
|---|
| 1532 | if (prog_error) | 
|---|
| 1533 | return; | 
|---|
| 1534 | par_getcomma(); | 
|---|
| 1535 | if (prog_error) | 
|---|
| 1536 | return; | 
|---|
| 1537 |  | 
|---|
| 1538 | vrx = par_getvar_ptr(); | 
|---|
| 1539 | if (prog_error) | 
|---|
| 1540 | return; | 
|---|
| 1541 | if (code_peek() == kwTYPE_SEP) { | 
|---|
| 1542 | par_getcomma(); | 
|---|
| 1543 | if (prog_error) | 
|---|
| 1544 | return; | 
|---|
| 1545 | vry = par_getvar_ptr(); | 
|---|
| 1546 | if (prog_error) | 
|---|
| 1547 | return; | 
|---|
| 1548 | } else | 
|---|
| 1549 | style = 1; | 
|---|
| 1550 |  | 
|---|
| 1551 | // initialize vars | 
|---|
| 1552 | v_free(type); | 
|---|
| 1553 | R.x = R.y = 0; | 
|---|
| 1554 |  | 
|---|
| 1555 | // | 
|---|
| 1556 | a = (B.y - A.y) * (D.x - C.x) - (B.x - A.x) * (D.y - C.y); | 
|---|
| 1557 | b = (A.x - C.x) * (D.y - C.y) - (A.y - C.y) * (D.x - C.x); | 
|---|
| 1558 | c = (A.x - C.x) * (B.y - A.y) - (A.y - C.y) * (B.x - A.x); | 
|---|
| 1559 |  | 
|---|
| 1560 | if (a == 0.0) | 
|---|
| 1561 | type->v.i = (b == 0.0) ? 3 : 2; | 
|---|
| 1562 | else { | 
|---|
| 1563 | if (a > 0.0) { | 
|---|
| 1564 | if ((b >= 0.0 && b <= a) && (c >= 0.0 && c <= a)) { | 
|---|
| 1565 | type->v.i = 1; | 
|---|
| 1566 | } else { | 
|---|
| 1567 | type->v.i = 0; | 
|---|
| 1568 | } | 
|---|
| 1569 | } else { | 
|---|
| 1570 | if ((b <= 0.0 && b >= a) && (c <= 0.0 && c >= a)) { | 
|---|
| 1571 | type->v.i = 1; | 
|---|
| 1572 | } else { | 
|---|
| 1573 | type->v.i = 0; | 
|---|
| 1574 | } | 
|---|
| 1575 | } | 
|---|
| 1576 | } | 
|---|
| 1577 |  | 
|---|
| 1578 | // | 
|---|
| 1579 | if (type->v.i == 1 || type->v.i == 0) { | 
|---|
| 1580 |  | 
|---|
| 1581 | if (b == a || c == a || c == 0.0) | 
|---|
| 1582 | if (type->v.i == 1) | 
|---|
| 1583 | type->v.i = 4;          // Special case | 
|---|
| 1584 |  | 
|---|
| 1585 | s = b / a; | 
|---|
| 1586 |  | 
|---|
| 1587 | if (C.x == D.x) | 
|---|
| 1588 | R.x = C.x; | 
|---|
| 1589 | else | 
|---|
| 1590 | R.x = A.x + ((B.x - A.x) * s); | 
|---|
| 1591 |  | 
|---|
| 1592 | if (C.y == D.y) | 
|---|
| 1593 | R.y = C.y; | 
|---|
| 1594 | else | 
|---|
| 1595 | R.y = A.y + ((B.y - A.y) * s); | 
|---|
| 1596 | } | 
|---|
| 1597 |  | 
|---|
| 1598 | // | 
|---|
| 1599 | if (style == 1) { | 
|---|
| 1600 | v_toarray1(vrx, 2); | 
|---|
| 1601 | v_setreal(v_elem(vrx, 0), R.x); | 
|---|
| 1602 | v_setreal(v_elem(vrx, 1), R.y); | 
|---|
| 1603 | } else { | 
|---|
| 1604 | v_setreal(vrx, R.x); | 
|---|
| 1605 | v_setreal(vry, R.y); | 
|---|
| 1606 | } | 
|---|
| 1607 | } | 
|---|
| 1608 |  | 
|---|
| 1609 | // | 
|---|
| 1610 | //  POLYEXT poly, BYREF xmin, BYREF ymin, BYREF xmax, BYREF ymax | 
|---|
| 1611 | // | 
|---|
| 1612 | void cmd_polyext() { | 
|---|
| 1613 | var_t *xmin, *ymin, *xmax, *ymax; | 
|---|
| 1614 | int count, i; | 
|---|
| 1615 | pt_t *poly = NULL; | 
|---|
| 1616 |  | 
|---|
| 1617 | count = par_getpoly(&poly); | 
|---|
| 1618 | if (prog_error) | 
|---|
| 1619 | return; | 
|---|
| 1620 |  | 
|---|
| 1621 | par_massget( "PPPP", &xmin, &ymin, &xmax, &ymax); | 
|---|
| 1622 | if (prog_error) { | 
|---|
| 1623 | free(poly); | 
|---|
| 1624 | return; | 
|---|
| 1625 | } | 
|---|
| 1626 |  | 
|---|
| 1627 | // initialize vars | 
|---|
| 1628 | v_free(xmin); | 
|---|
| 1629 | xmin->type = V_NUM; | 
|---|
| 1630 | v_free(xmax); | 
|---|
| 1631 | xmax->type = V_NUM; | 
|---|
| 1632 | v_free(ymin); | 
|---|
| 1633 | ymin->type = V_NUM; | 
|---|
| 1634 | v_free(ymax); | 
|---|
| 1635 | ymax->type = V_NUM; | 
|---|
| 1636 |  | 
|---|
| 1637 | if (count == 0) { | 
|---|
| 1638 | xmin->v.n = ymin->v.n = xmax->v.n = ymax->v.n = 0.0; | 
|---|
| 1639 | free(poly); | 
|---|
| 1640 | return; | 
|---|
| 1641 | } | 
|---|
| 1642 |  | 
|---|
| 1643 | xmin->v.n = xmax->v.n = poly[0].x; | 
|---|
| 1644 | ymin->v.n = ymax->v.n = poly[0].y; | 
|---|
| 1645 | for (i = 1; i < count; i++) { | 
|---|
| 1646 | if (poly[i].x > xmax->v.n) | 
|---|
| 1647 | xmax->v.n = poly[i].x; | 
|---|
| 1648 | if (poly[i].x < xmin->v.n) | 
|---|
| 1649 | xmin->v.n = poly[i].x; | 
|---|
| 1650 |  | 
|---|
| 1651 | if (poly[i].y > ymax->v.n) | 
|---|
| 1652 | ymax->v.n = poly[i].y; | 
|---|
| 1653 | if (poly[i].y < ymin->v.n) | 
|---|
| 1654 | ymin->v.n = poly[i].y; | 
|---|
| 1655 | } | 
|---|
| 1656 |  | 
|---|
| 1657 | free(poly); | 
|---|
| 1658 | } | 
|---|
| 1659 |  | 
|---|