Annotation of micropolis/src/sim/w_map.c, revision 1.1.1.1

1.1       root        1: /* w_map.c
                      2:  *
                      3:  * Micropolis, Unix Version.  This game was released for the Unix platform
                      4:  * in or about 1990 and has been modified for inclusion in the One Laptop
                      5:  * Per Child program.  Copyright (C) 1989 - 2007 Electronic Arts Inc.  If
                      6:  * you need assistance with this program, you may contact:
                      7:  *   http://wiki.laptop.org/go/Micropolis  or email  [email protected].
                      8:  * 
                      9:  * This program is free software: you can redistribute it and/or modify
                     10:  * it under the terms of the GNU General Public License as published by
                     11:  * the Free Software Foundation, either version 3 of the License, or (at
                     12:  * your option) any later version.
                     13:  * 
                     14:  * This program is distributed in the hope that it will be useful, but
                     15:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     17:  * General Public License for more details.  You should have received a
                     18:  * copy of the GNU General Public License along with this program.  If
                     19:  * not, see <http://www.gnu.org/licenses/>.
                     20:  * 
                     21:  *             ADDITIONAL TERMS per GNU GPL Section 7
                     22:  * 
                     23:  * No trademark or publicity rights are granted.  This license does NOT
                     24:  * give you any right, title or interest in the trademark SimCity or any
                     25:  * other Electronic Arts trademark.  You may not distribute any
                     26:  * modification of this program using the trademark SimCity or claim any
                     27:  * affliation or association with Electronic Arts Inc. or its employees.
                     28:  * 
                     29:  * Any propagation or conveyance of this program must include this
                     30:  * copyright notice and these terms.
                     31:  * 
                     32:  * If you convey this program (or any modifications of it) and assume
                     33:  * contractual liability for the program to recipients of it, you agree
                     34:  * to indemnify Electronic Arts for any liability that those contractual
                     35:  * assumptions impose on Electronic Arts.
                     36:  * 
                     37:  * You may not misrepresent the origins of this program; modified
                     38:  * versions of the program must be marked as such and not identified as
                     39:  * the original program.
                     40:  * 
                     41:  * This disclaimer supplements the one included in the General Public
                     42:  * License.  TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
                     43:  * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
                     44:  * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK.  THE ENTIRE RISK OF
                     45:  * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU.  ELECTRONIC ARTS
                     46:  * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
                     47:  * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
                     48:  * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
                     49:  * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
                     50:  * USAGE, OR TRADE PRACTICE.  ELECTRONIC ARTS DOES NOT WARRANT AGAINST
                     51:  * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
                     52:  * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
                     53:  * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
                     54:  * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
                     55:  * CORRECTED.  NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
                     56:  * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY.  SOME
                     57:  * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
                     58:  * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
                     59:  * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
                     60:  * NOT APPLY TO YOU.
                     61:  */
                     62: #include "sim.h"
                     63: 
                     64: 
                     65: Tcl_HashTable MapCmds;
                     66: 
                     67: 
                     68: extern Tk_ConfigSpec TileViewConfigSpecs[];
                     69: 
                     70: 
                     71: Ink *NewInk();
                     72: 
                     73: 
                     74: MapCmdconfigure(VIEW_ARGS)
                     75: {
                     76:   int result = TCL_OK;
                     77: 
                     78:   if (argc == 2) {
                     79:     result = Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs,
                     80:                              (char *) view, (char *) NULL, 0);
                     81:   } else if (argc == 3) {
                     82:     result = Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs,
                     83:                              (char *) view, argv[2], 0);
                     84:   } else {
                     85:     result = ConfigureTileView(interp, view, argc-2, argv+2,
                     86:                               TK_CONFIG_ARGV_ONLY);
                     87:   }
                     88:   return result;
                     89: }
                     90: 
                     91: MapCmdposition(VIEW_ARGS)
                     92: {
                     93:   if ((argc != 2) && (argc != 4)) {
                     94:     return TCL_ERROR;
                     95:   }
                     96:   if (argc == 4) {
                     97:     if ((Tcl_GetInt(interp, argv[2], &view->w_x) != TCL_OK)
                     98:        || (Tcl_GetInt(interp, argv[3], &view->w_y) != TCL_OK)) {
                     99:       return TCL_ERROR;
                    100:     }
                    101:   }
                    102:   sprintf(interp->result, "%d %d", view->w_x, view->w_y);
                    103:   return TCL_OK;
                    104: }
                    105: 
                    106: MapCmdsize(VIEW_ARGS)
                    107: {
                    108:   if ((argc != 2) && (argc != 4)) {
                    109:     return TCL_ERROR;
                    110:   }
                    111:   if (argc == 4) {
                    112:     int w, h;
                    113: 
                    114:     if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) {
                    115:       return TCL_ERROR;
                    116:     }
                    117:     if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) {
                    118:       return TCL_ERROR;
                    119:     }
                    120:     view->w_width = w;
                    121:     view->w_height = h;
                    122:   }
                    123:   sprintf(interp->result, "%d %d", view->w_width, view->w_height);
                    124:   return TCL_OK;
                    125: }
                    126: 
                    127: MapCmdMapState(VIEW_ARGS)
                    128: {
                    129:   int state;
                    130: 
                    131:   if ((argc != 2) && (argc != 3)) {
                    132:     return TCL_ERROR;
                    133:   }
                    134: 
                    135:   if (argc == 3) {
                    136:     if ((Tcl_GetInt(interp, argv[2], &state) != TCL_OK) ||
                    137:        (state < 0) || (state >= NMAPS)) {
                    138:       return TCL_ERROR;
                    139:     }
                    140: 
                    141:     DoSetMapState(view, state); Kick();
                    142:   }
                    143: 
                    144:   sprintf(interp->result, "%d", view->map_state);
                    145:   return TCL_OK;
                    146: }
                    147: 
                    148: MapCmdShowEditors(VIEW_ARGS)
                    149: {
                    150:   int val;
                    151: 
                    152:   if ((argc != 2) && (argc != 3)) {
                    153:     return TCL_ERROR;
                    154:   }
                    155: 
                    156:   if (argc == 3) {
                    157:     if (Tcl_GetInt(interp, argv[2], &val) != TCL_OK) {
                    158:       return TCL_ERROR;
                    159:     }
                    160: 
                    161:     view->show_editors = val;
                    162:   }
                    163: 
                    164:   sprintf(interp->result, "%d", view->show_editors);
                    165:   return TCL_OK;
                    166: }
                    167: 
                    168: MapCmdPanStart(VIEW_ARGS)
                    169: {
                    170:   int x, y, left, right, top, bottom, width, height;
                    171:   SimView *ed;
                    172: 
                    173:   if (argc != 4) {
                    174:     return TCL_ERROR;
                    175:   }
                    176: 
                    177:   if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
                    178:       (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
                    179:     return TCL_ERROR;
                    180:   }
                    181: 
                    182:   for (ed = sim->editor; ed != NULL; ed = ed->next) {
                    183:     if ((ed->x != view->x) || (ed->show_me == 0))
                    184:       continue;
                    185: 
                    186:     width = ed->w_width;
                    187:     height = ed->w_height;
                    188:     left = ed->pan_x - (width / 2);
                    189:     top = ed->pan_y - (height / 2);
                    190:     right = left + width;
                    191:     bottom = top + height;
                    192: 
                    193:     left = left * 3 / 16 - 4;
                    194:     top = top * 3 / 16 - 4;
                    195:     right = right * 3 / 16 + 4;
                    196:     bottom = bottom * 3 / 16 + 4;
                    197: 
                    198:     if ((x >= left) && (x <= right) &&
                    199:        (y >= top) && (y <= bottom)) {
                    200:       goto gotit;
                    201:     }
                    202:   }
                    203: 
                    204: gotit:
                    205:   view->last_x = x;
                    206:   view->last_y = y;
                    207:   view->track_info = (char *)ed;
                    208:   return TCL_OK;
                    209: }
                    210: 
                    211: MapCmdPanTo(VIEW_ARGS)
                    212: {
                    213:   int x, y, dx, dy;
                    214:   SimView *ed;
                    215: 
                    216:   if (argc != 4) {
                    217:     return TCL_ERROR;
                    218:   }
                    219: 
                    220:   if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
                    221:       (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
                    222:     return TCL_ERROR;
                    223:   }
                    224: 
                    225:   if ((ed = (SimView *)view->track_info) != NULL) {
                    226:     dx = x - view->last_x;
                    227:     dy = y - view->last_y;
                    228:     if (dx || dy) {
                    229:       view->last_x = x;
                    230:       view->last_y = y;
                    231:       dx = dx * 16 / 3;
                    232:       dy = dy * 16 / 3;
                    233: 
                    234:       ed->skip = 0;
                    235:       DoPanBy(ed, dx, dy); Kick();
                    236:     }
                    237:   }
                    238:   return TCL_OK;
                    239: }
                    240: 
                    241: MapCmdVisible(VIEW_ARGS)
                    242: {
                    243:   int visible;
                    244: 
                    245:   if ((argc != 2) && (argc != 3)) {
                    246:     return TCL_ERROR;
                    247:   }
                    248: 
                    249:   if (argc == 3) {
                    250:     if ((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) ||
                    251:        (visible < 0) || (visible > 1)) {
                    252:       return TCL_ERROR;
                    253:     }
                    254: 
                    255:     visible = visible && Tk_IsMapped(view->tkwin);
                    256:     view->visible = visible;
                    257:   }
                    258: 
                    259:   sprintf(interp->result, "%d", view->visible);
                    260:   return TCL_OK;
                    261: }
                    262: 
                    263: MapCmdViewAt(VIEW_ARGS)
                    264: {
                    265:   int x, y;
                    266: 
                    267:   if (argc != 4) {
                    268:     return TCL_ERROR;
                    269:   }
                    270: 
                    271:   if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
                    272:       (x < 0) || (x >= WORLD_X) ||
                    273:       (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) ||
                    274:       (y < 0) || (y >= WORLD_Y)) {
                    275:     return TCL_ERROR;
                    276:   }
                    277: 
                    278:   sprintf(interp->result, "Sorry Not Implemented Yet"); /* XXX */
                    279:   return TCL_OK;
                    280: }
                    281: 
                    282: 
                    283: map_command_init()
                    284: {
                    285:   int new;
                    286:   extern int TileViewCmd(CLIENT_ARGS);
                    287: 
                    288:   Tcl_CreateCommand(tk_mainInterp, "mapview", TileViewCmd,
                    289:                    (ClientData)MainWindow, (void (*)()) NULL);
                    290: 
                    291:   Tcl_InitHashTable(&MapCmds, TCL_STRING_KEYS);
                    292: 
                    293: #define MAP_CMD(name) HASHED_CMD(Map, name)
                    294: 
                    295:   MAP_CMD(configure);
                    296:   MAP_CMD(position);
                    297:   MAP_CMD(size);
                    298:   MAP_CMD(MapState);
                    299:   MAP_CMD(ShowEditors);
                    300:   MAP_CMD(PanStart);
                    301:   MAP_CMD(PanTo);
                    302:   MAP_CMD(Visible);
                    303:   MAP_CMD(ViewAt);
                    304: }
                    305: 
                    306: 
                    307: int
                    308: DoMapCmd(CLIENT_ARGS)
                    309: {
                    310:   SimView *view = (SimView *) clientData;
                    311:   Tcl_HashEntry *ent;
                    312:   int result = TCL_OK;
                    313:   int (*cmd)();
                    314: 
                    315:   if (argc < 2) {
                    316:     return TCL_ERROR;
                    317:   }
                    318: 
                    319:   if (ent = Tcl_FindHashEntry(&MapCmds, argv[1])) {
                    320:     cmd = (int (*)())ent->clientData;
                    321:     Tk_Preserve((ClientData) view);
                    322:     result = cmd(view, interp, argc, argv);
                    323:     Tk_Release((ClientData) view);
                    324:   } else {
                    325:     Tcl_AppendResult(interp, "unknown command name: \"",
                    326:                     argv[0], " ", argv[1], "\".", (char *) NULL);
                    327:     result = TCL_ERROR;
                    328:   }
                    329:   return result;
                    330: }
                    331: 
                    332: 
                    333: /*************************************************************************/
                    334: 
                    335: DoNewMap(SimView *view)
                    336: {
                    337:   sim->maps++; view->next = sim->map; sim->map = view;
                    338: /* NewMap = 1; */
                    339:   view->invalid = 1;
                    340: }
                    341: 
                    342: 
                    343: int DoUpdateMap(SimView *view)
                    344: {
                    345:   int dx, dy, i;
                    346: 
                    347:   view->updates++;
                    348: 
                    349: // fprintf(stderr, "UpdateMaps sim_skips %d skips %d skip %d visible %d\n", sim_skips, view->skips, view->skip, view->visible);
                    350: 
                    351:   if (!view->visible) {
                    352:     return 0;
                    353:   }
                    354: 
                    355:   if ((!ShakeNow) &&
                    356:       (!view->update) &&
                    357:       (sim_skips ||
                    358:        view->skips)) {
                    359:     if (sim_skips) {
                    360:       if (sim_skip > 0) {
                    361:        return 0;
                    362:       }
                    363:     } else {
                    364:       if (view->skip > 0) {
                    365:        --view->skip;
                    366:        return 0;
                    367:       } else {
                    368:        view->skip = view->skips;
                    369:       }
                    370:     }
                    371:   }
                    372: 
                    373:   view->update = 0;
                    374:   view->skip = 0;
                    375: 
                    376: //  view->invalid = 1;
                    377: 
                    378:   if (view->invalid || NewMap || ShakeNow) {
                    379: 
                    380:     view->invalid = 0;
                    381: 
                    382:     switch (view->type) {
                    383: 
                    384:     case X_Mem_View:
                    385:       MemDrawMap(view);
                    386:       break;
                    387: 
                    388:     case X_Wire_View:
                    389:       WireDrawMap(view);
                    390:       break;
                    391:     }
                    392: 
                    393:   }
                    394: 
                    395:   /* XXX: don't do this stuff if just redrawing overlay */
                    396: 
                    397:   for (dx = dy = i = 0; i < ShakeNow; i++) {
                    398:     dx += Rand(16) - 8;
                    399:     dy += Rand(16) - 8;
                    400:   }
                    401: 
                    402:   XCopyArea(view->x->dpy, view->pixmap, view->pixmap2, view->x->gc,
                    403:            dx, dy, view->w_width, view->w_height, 0, 0);
                    404:   DrawMapInk(view);
                    405: 
                    406:   /* XXX: do this if just redrawing overlay */
                    407: 
                    408:   XCopyArea(view->x->dpy, view->pixmap2,
                    409:            Tk_WindowId(view->tkwin), view->x->gc,
                    410:            0, 0, view->w_width, view->w_height, 0, 0);
                    411: 
                    412:   if (view->show_editors) {
                    413:     DrawMapEditorViews(view);
                    414:   }
                    415: 
                    416:   return 1;
                    417: }
                    418: 
                    419: 
                    420: DrawMapEditorViews(SimView *view)
                    421: {
                    422:   Pixmap pm = Tk_WindowId(view->tkwin);
                    423:   struct SimView *ed;
                    424:   int left, right, top, bottom, width, height;
                    425:   int mine;
                    426: 
                    427:   XSetLineAttributes(view->x->dpy, view->x->gc, 1,
                    428:                     LineSolid, CapButt, JoinBevel);
                    429: 
                    430:   for (ed = sim->editor; ed != NULL; ed = ed->next) {
                    431:     if ((ed->x != view->x) || (ed->show_me == 0))
                    432:       continue;
                    433: 
                    434:     width = ed->w_width;
                    435:     height = ed->w_height;
                    436:     left = ed->pan_x - (width / 2);
                    437:     top = ed->pan_y - (height / 2);
                    438:     right = left + width;
                    439:     bottom = top + height;
                    440: 
                    441:     left = left * 3 / 16;
                    442:     top = top * 3 / 16;
                    443:     right = right * 3 / 16;
                    444:     bottom = bottom * 3 / 16;
                    445:     width = right - left;
                    446:     height = bottom - top;
                    447: 
                    448:     XSetForeground(view->x->dpy, view->x->gc,
                    449:                   view->pixels[COLOR_WHITE]);
                    450:     XDrawRectangle(view->x->dpy, pm, view->x->gc,
                    451:                   left - 3, top - 3, width + 3, height + 3);
                    452: 
                    453:     XSetForeground(view->x->dpy, view->x->gc,
                    454:                   view->pixels[COLOR_BLACK]);
                    455:     XDrawRectangle(view->x->dpy, pm, view->x->gc,
                    456:                   left - 1, top - 1, width + 3, height + 3);
                    457: 
                    458:     XSetForeground(view->x->dpy, view->x->gc,
                    459:                   view->pixels[COLOR_YELLOW]);
                    460:     XDrawRectangle(view->x->dpy, pm, view->x->gc,
                    461:                   left - 2, top - 2, width + 3, height + 3);
                    462:   }
                    463: }
                    464: 
                    465: 
                    466: /* 
                    467:  * Sending the whole image is 108108 bytes.
                    468:  * Sending points is 4.4 bytes per point.
                    469:  * One image is as big as 24570 points.
                    470:  * But we have to sort these dang things.
                    471:  */
                    472: 
                    473: #define MAX_PIX 256
                    474: int max_pix = MAX_PIX;
                    475: 
                    476: struct Pix {
                    477:   long color;
                    478:   short x, y;
                    479: };
                    480: 
                    481: struct Pix pix[MAX_PIX];
                    482: 
                    483: 
                    484: CompareColor(struct Pix *p1, struct Pix *p2)
                    485: {
                    486:   register char c1 = p1->color, c2 = p2->color;
                    487: 
                    488:   if (c1 == c2)
                    489:     return (0);
                    490:   return ((c1 < c2) ? -1 : 1);
                    491: }
                    492: 
                    493: 
                    494: WireDrawMap(SimView *view)
                    495: {
                    496:   int different, x, y, i, last, pts;
                    497:   unsigned char *old, *new;
                    498:   XPoint *points;
                    499: 
                    500:   if (!view->x->color) {
                    501:     MemDrawMap(view);
                    502:     return;
                    503:   }
                    504: 
                    505:   memcpy(view->other_data, view->data, view->line_bytes * view->m_height); /* XXX: handle depth */
                    506:   MemDrawMap(view);
                    507: 
                    508:   old = view->other_data; new = view->data; /* XXX: handle depth */
                    509:   different = 0;
                    510: 
                    511:   /* Scan the pixels that have changed */
                    512:   for (y = 0; y < view->m_height; y++) {
                    513:     for (x = 0; x < view->m_width; x++) {
                    514:       if (old[x] != new[x]) {
                    515:        if (different >= max_pix) {
                    516:          /* Wow, lots of the pixels have changed.
                    517:             Maybe we ought to just do it the hard way. */ 
                    518:          XPutImage(view->x->dpy, view->pixmap, view->x->gc, view->image, 
                    519:                    0, 0, 0, 0, view->m_width, view->m_height);
                    520:          return;
                    521:        }
                    522:        pix[different].color = new[x];
                    523:        pix[different].x = x;
                    524:        pix[different].y = y;
                    525:        different++;
                    526:       }
                    527:     }
                    528:     old += view->line_bytes; new += view->line_bytes; /* XXX: handle depth */
                    529:   }
                    530: 
                    531:   /* Whew, the images are identical! */
                    532:   if (different == 0)
                    533:     return;
                    534: 
                    535: #if 1
                    536: 
                    537:   /* Always draw the whole pixmap, for now. */
                    538:   XPutImage(view->x->dpy, view->pixmap, view->x->gc, view->image, 
                    539:            0, 0, 0, 0, view->m_width, view->m_height);
                    540: 
                    541: #else
                    542: 
                    543:   /* TODO: Fix this. I disabled this incremental drawing code for now since it seems to be buggy. */
                    544: 
                    545:   /* Sort the changed pixels by their color */
                    546:   qsort(pix, different, sizeof (struct Pix), (int (*)())CompareColor);
                    547: 
                    548:   /* Draw the points of each color that have changed */
                    549:   points = (XPoint *)malloc(sizeof (XPoint) * different);
                    550:   last = 0; pts = 0;
                    551:   for (i = 0; i <= different; i++) {
                    552:     if ((i == different) ||
                    553:        (pix[i].color != pix[last].color)) {
                    554:       XSetForeground(view->x->dpy, view->x->gc, pix[last].color);
                    555:       XDrawPoints(view->x->dpy, view->pixmap, view->x->gc,
                    556:                  points, pts, CoordModeOrigin);
                    557:       if (i == different)
                    558:        break;
                    559:       pts = 0;
                    560:       last = i;
                    561:     }
                    562:     points[pts].x = pix[i].x;
                    563:     points[pts].y = pix[i].y;
                    564:     pts++;
                    565:   }
                    566:   free(points);
                    567: 
                    568: #endif
                    569: 
                    570: }
                    571: 
                    572: 
                    573: DrawMapInk(SimView *view)
                    574: {
                    575:   Pixmap pm = view->pixmap2;
                    576:   SimView *v;
                    577:   Ink *ink, *ink2 = NewInk();
                    578:   int i, X, Y, x, y;
                    579: 
                    580:   XSetLineAttributes(view->x->dpy, view->x->gc, 0,
                    581:                     LineSolid, CapButt, JoinBevel);
                    582: 
                    583:   for (ink = sim->overlay; ink != NULL; ink = ink->next) {
                    584:     X = ink->x; x = (X * 3) >>4;
                    585:     Y = ink->y; y = (Y * 3) >>4;
                    586:     
                    587:     if (ink->length <= 1) {
                    588:       XSetForeground(view->x->dpy, view->x->gc,
                    589:                     view->pixels[ink->color]);
                    590:       XFillArc(view->x->dpy, pm, view->x->gc,
                    591:               ink->x - 1, ink->y - 1, 1, 1, 0, 360 * 64);
                    592:     } else {
                    593:       StartInk(ink2, x, y);
                    594: 
                    595:       for (i = 1; i < ink->length; i++) {
                    596:        X += ink->points[i].x; x = (X * 3) >>4;
                    597:        Y += ink->points[i].y; y = (Y * 3) >>4;
                    598:        AddInk(ink2, x, y);
                    599:       }
                    600: 
                    601:       XSetForeground(view->x->dpy, view->x->gc,
                    602:                     view->pixels[ink->color]);
                    603:       XDrawLines(view->x->dpy, pm, view->x->gc,
                    604:                 ink2->points, ink2->length, CoordModePrevious);
                    605:     }
                    606:   }
                    607: 
                    608:   FreeInk(ink2);
                    609: }
                    610: 
                    611: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.