diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2018-10-20 17:54:38 +0200 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2018-10-20 17:54:38 +0200 |
commit | 69fcfa5f570e247c58cbc35eb48c5e55eaaa4c8e (patch) | |
tree | 6e8aa19578c2657cad60c3969d9018c4c4a9584a /elements.c | |
parent | 332f65d9afdb5cb8e4d62883ad522f430ab39208 (diff) | |
parent | ca2442640f4394296d9d6b0c42d41d399dbf9667 (diff) |
Merge tag 'upstream/3.9.73+dfsg.1'
Upstream version 3.9.73+dfsg.1
Diffstat (limited to 'elements.c')
-rw-r--r-- | elements.c | 634 |
1 files changed, 534 insertions, 100 deletions
@@ -41,7 +41,6 @@ /*----------------------------------------------------------------------*/ extern Display *dpy; /* Works well to make this globally accessible */ -extern int *appcolors; extern Cursor appcursors[NUM_CURSORS]; extern XCWindowData *areawin; extern Globaldata xobjs; @@ -50,6 +49,10 @@ extern fontinfo *fonts; extern short fontcount; extern char _STR[150], _STR2[250]; extern int number_colors; +extern colorindex *colorlist; +#if !defined(HAVE_CAIRO) +extern Pixmap dbuf; +#endif extern double atan2(); @@ -76,6 +79,9 @@ u_char texttype; /* calling routine. */ /* "pintype" is NORMAL, LOCAL, GLOBAL, or INFO */ /* "x" and "y" are the label coordinates. */ +/* if "dochange" is FALSE, then this label is being drawn */ +/* as part of a font or library and should not cause */ +/* changes count to increment. */ /* */ /* Other properties must be set individually by the calling */ /* routine. */ @@ -84,7 +90,7 @@ u_char texttype; /*--------------------------------------------------------------*/ labelptr new_label(objinstptr destinst, stringpart *strptr, int pintype, - int x, int y) + int x, int y, u_char dochange) { labelptr *newlab; objectptr destobject; @@ -105,7 +111,7 @@ labelptr new_label(objinstptr destinst, stringpart *strptr, int pintype, calcbboxvalues(locdestinst, (genericptr *)newlab); updatepagebounds(destobject); - incr_changes(destobject); + if (dochange != (u_char)0) incr_changes(destobject); return *newlab; } @@ -126,7 +132,7 @@ labelptr new_simple_label(objinstptr destinst, char *cstr, strptr->nextpart = NULL; strptr->data.string = cstr; - return new_label(destinst, strptr, pintype, x, y); + return new_label(destinst, strptr, pintype, x, y, (u_char)0); } /*--------------------------------------------------------------*/ @@ -328,6 +334,9 @@ void remove_element(objinstptr destinst, genericptr genelem) void pathdefaults(pathptr newpath, int x, int y) { + UNUSED(x); + UNUSED(y); + newpath->style = NORMAL; newpath->width = areawin->linewidth; newpath->style = areawin->style; @@ -345,7 +354,7 @@ void instancedefaults(objinstptr newinst, objectptr thisobj, int x, int y) { newinst->position.x = x; newinst->position.y = y; - newinst->rotation = 0; + newinst->rotation = 0.0; newinst->scale = 1.0; newinst->style = LINE_INVARIANT; newinst->thisobject = thisobj; @@ -399,7 +408,7 @@ void drawdot(int xpos, int ypos) void labeldefaults(labelptr newlabel, u_char dopin, int x, int y) { - newlabel->rotation = 0; + newlabel->rotation = 0.0; newlabel->color = areawin->color; newlabel->scale = areawin->textscale; newlabel->string = (stringpart *)malloc(sizeof(stringpart)); @@ -416,7 +425,7 @@ void labeldefaults(labelptr newlabel, u_char dopin, int x, int y) else if (dopin == GLOBAL) newlabel->color = GLOBALPINCOLOR; else if (dopin == INFO) newlabel->color = INFOLABELCOLOR; - newlabel->justify = areawin->justify; + newlabel->anchor = areawin->anchor; newlabel->position.x = x; newlabel->position.y = y; } @@ -445,12 +454,13 @@ void textbutton(u_char dopin, int x, int y) labeldefaults(*newlabel, dopin, userpt.x, userpt.y); tmpheight = (short)(TEXTHEIGHT * (*newlabel)->scale); - userpt.y -= ((*newlabel)->justify & NOTBOTTOM) ? - (((*newlabel)->justify & TOP) ? tmpheight : tmpheight / 2) : 0; - UDrawTLine(*newlabel); + userpt.y -= ((*newlabel)->anchor & NOTBOTTOM) ? + (((*newlabel)->anchor & TOP) ? tmpheight : tmpheight / 2) : 0; areawin->origin.x = userpt.x; areawin->origin.y = userpt.y; areawin->textpos = 1; /* Text position is *after* the font declaration */ + + text_mode_draw(xcDRAW_EDIT, *newlabel); } /*----------------------------------------------------------------------*/ @@ -519,7 +529,7 @@ Boolean labeltext(int keypressed, char *clientdata) stringpart *curpos, *labelbuf; int locpos; Boolean r = True, do_redraw = False; - short tmplength, tmpheight, cfont; + short cfont; TextExtents tmpext; TechPtr oldtech, newtech; @@ -527,6 +537,7 @@ Boolean labeltext(int keypressed, char *clientdata) if (curlabel == NULL || curlabel->type != LABEL) { Wprintf("Error: Bad label string"); + text_mode_draw(xcDRAW_EMPTY, curlabel); eventmode = NORMAL_MODE; return FALSE; } @@ -535,8 +546,6 @@ Boolean labeltext(int keypressed, char *clientdata) curpos = findstringpart(areawin->textpos, &locpos, curlabel->string, areawin->topinstance); - UDrawTLine(curlabel); - if (clientdata != NULL && keypressed == TEXT_DELETE) { if (areawin->textpos > 1) { int curloc, strpos; @@ -578,15 +587,21 @@ Boolean labeltext(int keypressed, char *clientdata) int curloc, strpos; stringpart *strptr; - strptr = findstringpart(areawin->textpos - 1, &curloc, curlabel->string, + strpos = areawin->textpos - 1; + strptr = findstringpart(strpos, &curloc, curlabel->string, areawin->topinstance); - if ((curloc < 0) && (strptr != NULL) && (strptr->type == PARAM_END)) { - undrawtext(curlabel); - while (strptr->type != PARAM_START) - strptr = findstringpart(--strpos, &curloc, curlabel->string, + if (curloc > 0) strpos -= curloc; /* move to beginning of string */ + if ((strptr != NULL) && (strptr->type != PARAM_START) && (strpos > 0)) { + strpos--; + strptr = findstringpart(strpos--, &curloc, curlabel->string, areawin->topinstance); - unmakeparam(curlabel, strptr); - do_redraw = True; + } + if ((strptr != NULL) && (strptr->type == PARAM_START)) { + if (strpos >= 0) { + undrawtext(curlabel); + unmakeparam(curlabel, areawin->topinstance, strptr); + do_redraw = True; + } } } } @@ -629,14 +644,17 @@ Boolean labeltext(int keypressed, char *clientdata) } if ((!hasstuff) && (eventmode == CATTEXT_MODE)) { /* can't have null labels! */ - undo_action(); - XcSetFunction(GXcopy); - redrawtext(curlabel); - Wprintf("Object must have a name!"); - eventmode = CATALOG_MODE; + undo_action(); + redrawtext(curlabel); + areawin->redraw_needed = False; /* ignore previous redraw requests */ + text_mode_draw(xcDRAW_FINAL, curlabel); + Wprintf("Object must have a name!"); + eventmode = CATALOG_MODE; } else if (!hasstuff) { - eventmode = NORMAL_MODE; + areawin->redraw_needed = False; /* ignore previous redraw requests */ + text_mode_draw(xcDRAW_FINAL, curlabel); + eventmode = NORMAL_MODE; } else if (eventmode == CATTEXT_MODE) { objectptr libobj; @@ -673,7 +691,6 @@ Boolean labeltext(int keypressed, char *clientdata) curlabel->string->nextpart->data.string, (strlen(libobj->name) + 1) * sizeof(char)); strcpy(curlabel->string->nextpart->data.string, libobj->name); - XcSetFunction(GXcopy); redrawtext(curlabel); } AddObjectTechnology(libobj); @@ -706,10 +723,14 @@ Boolean labeltext(int keypressed, char *clientdata) Wprintf("Error: Cannot match name to any object, page, or library!"); refresh(NULL, NULL, NULL); } + areawin->redraw_needed = False; /* ignore previous redraw requests */ + text_mode_draw(xcDRAW_FINAL, curlabel); eventmode = CATALOG_MODE; } else { /* (hasstuff && eventmode != CATTEXT_MODE) */ + areawin->redraw_needed = False; /* ignore previous redraw requests */ + text_mode_draw(xcDRAW_FINAL, curlabel); eventmode = NORMAL_MODE; incr_changes(topobject); if (curlabel->pin != False) invalidate_netlist(topobject); @@ -824,7 +845,6 @@ Boolean labeltext(int keypressed, char *clientdata) (*newlabel)->position.x += (points[3].x - points2[3].x); (*newlabel)->position.y += (points[3].y - points2[3].y); - XcSetFunction(GXcopy); redrawtext(*newlabel); do_redraw = True; } @@ -836,6 +856,7 @@ Boolean labeltext(int keypressed, char *clientdata) oparamptr ops; stringpart *newpart; Boolean errcond = False; + TextLinesInfo tlinfo; /* erase first before redrawing unless the string is empty */ undrawtext(curlabel); @@ -843,8 +864,13 @@ Boolean labeltext(int keypressed, char *clientdata) /* Get text width first. Don't back up over spaces; this */ /* allows the margin width to be padded out with spaces. */ - if (keypressed == MARGINSTOP) - tmpext = ULength(curlabel, areawin->topinstance, areawin->textpos, NULL); + if (keypressed == MARGINSTOP) { + tlinfo.dostop = areawin->textpos; + tlinfo.tbreak = NULL; + tlinfo.padding = NULL; + tmpext = ULength(curlabel, areawin->topinstance, &tlinfo); + if (tlinfo.padding != NULL) free(tlinfo.padding); + } if (locpos > 0) { if (keypressed == MARGINSTOP) { @@ -864,7 +890,7 @@ Boolean labeltext(int keypressed, char *clientdata) newpart->type = keypressed; switch (keypressed) { case RETURN: - // Identify this as an explicitly placed line break + /* Identify this as an explicitly placed line break */ newpart->data.flags = 0; break; case FONT_SCALE: @@ -969,11 +995,11 @@ Boolean labeltext(int keypressed, char *clientdata) /* Generate automatic line breaks if there is a MARGINSTOP directive */ CheckMarginStop(curlabel, areawin->topinstance, TRUE); - XcSetFunction(GXcopy); redrawtext(curlabel); } - UDrawTLine(curlabel); + areawin->redraw_needed = False; /* ignore previous full redraw requests */ + text_mode_draw(xcDRAW_EDIT, curlabel); if (r || do_redraw) { @@ -1005,34 +1031,34 @@ void textreturn() labeltext(TEXT_RETURN, (char *)1); } -/*-------------------------------------*/ -/* Change the justification of a label */ -/*-------------------------------------*/ +/*--------------------------------------*/ +/* Change the anchoring of a label */ +/*--------------------------------------*/ -void rejustify(short mode) +void reanchor(short mode) { labelptr curlabel = NULL; short *tsel; short jsave; Boolean preselected = False, changed = False; - static short transjust[] = {15, 13, 12, 7, 5, 4, 3, 1, 0}; + static short transanchor[] = {15, 13, 12, 7, 5, 4, 3, 1, 0}; if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) { curlabel = TOLABEL(EDITPART); UDrawTLine(curlabel); undrawtext(curlabel); - jsave = curlabel->justify; - curlabel->justify = transjust[mode] | - (curlabel->justify & NONJUSTFIELD); - if (jsave != curlabel->justify) { - register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance, + jsave = curlabel->anchor; + curlabel->anchor = transanchor[mode] | + (curlabel->anchor & NONANCHORFIELD); + if (jsave != curlabel->anchor) { + register_for_undo(XCF_Anchor, UNDO_MORE, areawin->topinstance, (genericptr)curlabel, (int)jsave); changed = True; } redrawtext(curlabel); UDrawTLine(curlabel); - setfontmarks(-1, curlabel->justify); + setfontmarks(-1, curlabel->anchor); } else { if (areawin->selects == 0) { @@ -1045,12 +1071,12 @@ void rejustify(short mode) areawin->selects; tsel++) { if (SELECTTYPE(tsel) == LABEL) { curlabel = SELTOLABEL(tsel); - jsave = curlabel->justify; + jsave = curlabel->anchor; undrawtext(curlabel); - curlabel->justify = transjust[mode] | - (curlabel->justify & NONJUSTFIELD); - if (jsave != curlabel->justify) { - register_for_undo(XCF_Justify, UNDO_MORE, areawin->topinstance, + curlabel->anchor = transanchor[mode] | + (curlabel->anchor & NONANCHORFIELD); + if (jsave != curlabel->anchor) { + register_for_undo(XCF_Anchor, UNDO_MORE, areawin->topinstance, (genericptr)curlabel, (int)jsave); changed = True; } @@ -1062,7 +1088,7 @@ void rejustify(short mode) draw_all_selected(); } if (curlabel == NULL) - Wprintf("No labels chosen to rejustify"); + Wprintf("No labels chosen to reanchor"); else if (changed) { pwriteback(areawin->topinstance); calcbbox(areawin->topinstance); @@ -1112,9 +1138,7 @@ void splinebutton(int x, int y) addcycle((genericptr *)newspline, 3, 0); makerefcycle((*newspline)->cycle, 3); - XcSetXORFg(areawin->color, BACKGROUND); - XcSetFunction(GXxor); - UDrawSpline(*newspline, xobjs.pagelist[areawin->page]->wirewidth); + spline_mode_draw(xcDRAW_EDIT, *newspline); xcAddEventHandler(areawin->area, PointerMotionMask, False, (xcEventHandler)trackelement, NULL); @@ -1137,7 +1161,7 @@ void splinebutton(int x, int y) void updatepath(pathptr thepath) { genericptr *ggen, *ngen; - short locparts, cycle, ncycle; + short locparts, cycle; pointselect *cptr; polyptr thispoly; splineptr thisspline; @@ -1262,9 +1286,7 @@ void arcbutton(int x, int y) arcdefaults(*newarc, userpt.x, userpt.y); addcycle((genericptr *)newarc, 0, 0); - XcSetXORFg((*newarc)->color, BACKGROUND); - XcSetFunction(GXxor); - UDrawArc(*newarc, xobjs.pagelist[areawin->page]->wirewidth); + arc_mode_draw(xcDRAW_EDIT, *newarc); xcAddEventHandler(areawin->area, PointerMotionMask, False, (xcEventHandler)trackarc, NULL); @@ -1282,6 +1304,7 @@ void trackarc(xcWidget w, caddr_t clientdata, caddr_t calldata) arcptr newarc; double adjrat; short cycle; + UNUSED(w); UNUSED(clientdata); UNUSED(calldata); newarc = TOARC(EDITPART); @@ -1289,9 +1312,6 @@ void trackarc(xcWidget w, caddr_t clientdata, caddr_t calldata) u2u_snap(&newpos); if (areawin->save.x == newpos.x && areawin->save.y == newpos.y) return; - UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth); - UDrawXLine(areawin->save, newarc->position); - cycle = (newarc->cycle == NULL) ? -1 : newarc->cycle->number; if (cycle == 1 || cycle == 2) { float *angleptr, tmpang; @@ -1331,14 +1351,12 @@ void trackarc(xcWidget w, caddr_t clientdata, caddr_t calldata) calcarc(newarc); - XcSetXORFg(newarc->color, BACKGROUND); - UDrawArc(newarc, xobjs.pagelist[areawin->page]->wirewidth); - UDrawXLine(newpos, newarc->position); - printpos(newpos.x, newpos.y); - areawin->save.x = newpos.x; areawin->save.y = newpos.y; + arc_mode_draw(xcDRAW_EDIT, newarc); + printpos(newpos.x, newpos.y); + flusharea(); } @@ -1386,9 +1404,7 @@ void boxbutton(int x, int y) snap(x, y, &userpt); polydefaults(*newbox, 4, userpt.x, userpt.y); - XcSetXORFg((*newbox)->color, BACKGROUND); - XcSetFunction(GXxor); - UDrawPolygon(*newbox, xobjs.pagelist[areawin->page]->wirewidth); + poly_mode_draw(xcDRAW_EDIT, *newbox); xcAddEventHandler(areawin->area, PointerMotionMask, False, (xcEventHandler)trackbox, NULL); @@ -1405,6 +1421,7 @@ void trackbox(xcWidget w, caddr_t clientdata, caddr_t calldata) XPoint newpos; polyptr newbox; pointlist pointptr; + UNUSED(w); UNUSED(clientdata); UNUSED(calldata); newbox = TOPOLY(EDITPART); newpos = UGetCursorPos(); @@ -1412,14 +1429,11 @@ void trackbox(xcWidget w, caddr_t clientdata, caddr_t calldata) if (areawin->save.x == newpos.x && areawin->save.y == newpos.y) return; - UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth); - pointptr = newbox->points + 1; pointptr->y = newpos.y; pointptr++; pointptr->y = newpos.y; pointptr->x = newpos.x; pointptr++; pointptr->x = newpos.x; - XcSetXORFg(newbox->color, BACKGROUND); - UDrawPolygon(newbox, xobjs.pagelist[areawin->page]->wirewidth); + poly_mode_draw(xcDRAW_EDIT, newbox); printpos(newpos.x, newpos.y); areawin->save.x = newpos.x; @@ -1441,6 +1455,7 @@ void trackwire(xcWidget w, caddr_t clientdata, caddr_t calldata) { XPoint newpos, upos, *tpoint; polyptr newwire; + UNUSED(w); UNUSED(clientdata); UNUSED(calldata); newwire = TOPOLY(EDITPART); @@ -1457,13 +1472,12 @@ void trackwire(xcWidget w, caddr_t clientdata, caddr_t calldata) if (areawin->save.x != newpos.x || areawin->save.y != newpos.y) { tpoint = newwire->points + newwire->number - 1; - UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth); if (areawin->manhatn && (newwire->number > 2)) manhattanize(&newpos, newwire, -1, TRUE); tpoint->x = newpos.x; tpoint->y = newpos.y; - XcSetXORFg(newwire->color, BACKGROUND); - UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth); + XcTopSetForeground(newwire->color); + poly_mode_draw(xcDRAW_EDIT, newwire); areawin->save.x = newpos.x; areawin->save.y = newpos.y; printpos(newpos.x, newpos.y); @@ -1500,9 +1514,7 @@ void startwire(XPoint *userpt) pointptr->x = (pointptr + 1)->x = areawin->save.x = userpt->x; pointptr->y = (pointptr + 1)->y = areawin->save.y = userpt->y; - XcSetXORFg((*newwire)->color, BACKGROUND); - XcSetFunction(GXxor); - UDrawPolygon(*newwire, xobjs.pagelist[areawin->page]->wirewidth); + poly_mode_draw(xcDRAW_EDIT, *newwire); xcAddEventHandler(areawin->area, PointerMotionMask, False, (xcEventHandler)trackwire, NULL); @@ -1632,12 +1644,11 @@ void findconstrained(polyptr lastpoly) void trackelement(xcWidget w, caddr_t clientdata, caddr_t calldata) { - XPoint newpos, origpt, *curpt; - polyptr editpoly; - genericptr *ggen; - short cycle, *selobj; + XPoint newpos, *curpt; + short *selobj; pointselect *cptr; int deltax, deltay; + UNUSED(w); UNUSED(clientdata); UNUSED(calldata); newpos = UGetCursorPos(); u2u_snap(&newpos); @@ -1673,20 +1684,32 @@ void trackelement(xcWidget w, caddr_t clientdata, caddr_t calldata) curpt = &(TOGRAPHIC(EDITPART)->position); break; } - origpt = *curpt; deltax = newpos.x - curpt->x; deltay = newpos.y - curpt->y; /* Now adjust all edited elements relative to the reference point */ - for (selobj = areawin->selectlist; selobj < areawin->selectlist + - areawin->selects; selobj++) - { - easydraw(*selobj, DOFORALL); - editpoints(SELTOGENERICPTR(selobj), deltax, deltay); - XcSetXORFg(topobject->plist[*selobj]->color, BACKGROUND); - easydraw(*selobj, DOFORALL); - } + areawin->selects; selobj++) { + if (eventmode == ARC_MODE || eventmode == EARC_MODE) + editpoints(SELTOGENERICPTR(selobj), deltax, deltay); + else if (eventmode == SPLINE_MODE || eventmode == ESPLINE_MODE) + editpoints(SELTOGENERICPTR(selobj), deltax, deltay); + else if (eventmode == BOX_MODE || eventmode == EPOLY_MODE + || eventmode == WIRE_MODE) + editpoints(SELTOGENERICPTR(selobj), deltax, deltay); + else if (eventmode == EPATH_MODE) + editpoints(SELTOGENERICPTR(selobj), deltax, deltay); + } + + if (eventmode == ARC_MODE || eventmode == EARC_MODE) + arc_mode_draw(xcDRAW_EDIT, TOARC(EDITPART)); + else if (eventmode == SPLINE_MODE || eventmode == ESPLINE_MODE) + spline_mode_draw(xcDRAW_EDIT, TOSPLINE(EDITPART)); + else if (eventmode == BOX_MODE || eventmode == EPOLY_MODE + || eventmode == WIRE_MODE) + poly_mode_draw(xcDRAW_EDIT, TOPOLY(EDITPART)); + else if (eventmode == EPATH_MODE) + path_mode_draw(xcDRAW_EDIT, TOPATH(EDITPART)); printpos(newpos.x, newpos.y); areawin->save.x = newpos.x; @@ -1830,11 +1853,9 @@ void unjoin() /* for each selected path or polygon */ - XcSetFunction(GXcopy); - for (selectobj = areawin->selectlist; selectobj < areawin->selectlist + areawin->selects; selectobj++) { - XSetForeground(dpy, areawin->gc, BACKGROUND); + SetForeground(dpy, areawin->gc, BACKGROUND); if (SELECTTYPE(selectobj) == PATH) { oldpath = SELTOPATH(selectobj); @@ -2226,9 +2247,6 @@ void wire_op(int op, int x, int y) newwire = TOPOLY(EDITPART); - /* This undraws the wire */ - UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth); - if (areawin->attachto >= 0) { XPoint apos; findattach(&apos, NULL, &userpt); @@ -2295,13 +2313,13 @@ void wire_op(int op, int x, int y) newwire->number--; } - XcSetFunction(GXcopy); - XcTopSetForeground(newwire->color); incr_changes(topobject); if (!nonnetwork(newwire)) invalidate_netlist(topobject); register_for_undo(XCF_Wire, UNDO_MORE, areawin->topinstance, newwire); + poly_mode_draw(xcDRAW_FINAL, newwire); } - UDrawPolygon(newwire, xobjs.pagelist[areawin->page]->wirewidth); + else + poly_mode_draw(xcDRAW_EDIT, newwire); if (op == XCF_Cancel_Last) checkwarp(newwire->points + newwire->number - 1); } @@ -2313,3 +2331,419 @@ void wire_op(int op, int x, int y) } /*-------------------------------------------------------------------------*/ +/* Helper functions for the xxx_mode_draw functions */ +/* Functions to be used around the drawing of the edited element */ +/* begin_event_mode_drawing starts double buffering and copies the */ +/* fixed pixmap. end_event_mode stops the double buffering and displays */ +/* everything on screen. */ +/*-------------------------------------------------------------------------*/ + +#ifndef HAVE_CAIRO +static Window old_win; +#endif /* !HAVE_CAIRO */ + +static void begin_event_mode_drawing(void) +{ + /* Start double buffering */ +#ifdef HAVE_CAIRO + cairo_identity_matrix(areawin->cr); + cairo_translate(areawin->cr, areawin->panx, areawin->pany); + cairo_push_group(areawin->cr); +#else /* HAVE_CAIRO */ + old_win = areawin->window; + areawin->window = (Window) dbuf; +#endif /* HAVE_CAIRO */ + + /* Copy background pixmap with the element(s) not currently being edited */ +#ifdef HAVE_CAIRO + if (areawin->panx || areawin->pany) { + SetForeground(dpy, areawin->gc, BACKGROUND); + cairo_paint(areawin->cr); + } + cairo_set_source(areawin->cr, areawin->fixed_pixmap); + cairo_paint(areawin->cr); +#else /* HAVE_CAIRO */ + if (areawin->panx || areawin->pany) { + int x = max(0, -areawin->panx); + int y = max(0, -areawin->pany); + unsigned int w = areawin->width - x; + unsigned int h = areawin->height - y; + SetForeground(dpy, areawin->gc, BACKGROUND); + XSetFillStyle(dpy, areawin->gc, FillSolid); + XFillRectangle(dpy, areawin->window, areawin->gc, 0, 0, areawin->width, + areawin->height); + XCopyArea(dpy, areawin->fixed_pixmap, areawin->window, areawin->gc, + x, y, w, h, max(0, areawin->panx), max(0, areawin->pany)); + } + else + XCopyArea(dpy, areawin->fixed_pixmap, areawin->window, areawin->gc, 0, 0, + areawin->width, areawin->height, 0, 0); +#endif /* HAVE_CAIRO */ + + areawin->redraw_ongoing = True; + newmatrix(); +} + +static void end_event_mode_drawing(void) +{ + /* End double buffering */ +#ifdef HAVE_CAIRO + cairo_pop_group_to_source(areawin->cr); + cairo_paint(areawin->cr); +#else /* HAVE_CAIRO */ + areawin->window = old_win; + XCopyArea(dpy, dbuf, areawin->window, areawin->gc, 0, 0, areawin->width, + areawin->height, 0, 0); +#endif /* HAVE_CAIRO */ + + areawin->redraw_ongoing = False; +} + +/*-------------------------------------------------------------------------*/ +/* Helper functions for the xxx_mode_draw functions */ +/* Functions to be used when finishing the element. The final state is */ +/* drawn into the fixed pixmap, which is show when the */ +/* end_event_mode_drawing_final is called */ +/* (Sorry about the name :-) ) */ +/*-------------------------------------------------------------------------*/ + +static void begin_event_mode_drawing_final(void) +{ +#ifdef HAVE_CAIRO + cairo_identity_matrix(areawin->cr); + cairo_push_group(areawin->cr); + cairo_set_source(areawin->cr, areawin->fixed_pixmap); + cairo_paint(areawin->cr); +#else /* HAVE_CAIRO */ + old_win = areawin->window; + areawin->window = (Window) areawin->fixed_pixmap; +#endif /* HAVE_CAIRO */ + + areawin->redraw_ongoing = True; + newmatrix(); +} + +static void end_event_mode_drawing_final(void) +{ +#ifdef HAVE_CAIRO + cairo_pattern_destroy(areawin->fixed_pixmap); + areawin->fixed_pixmap = cairo_pop_group(areawin->cr); +#else /* HAVE_CAIRO */ + areawin->window = old_win; +#endif /* HAVE_CAIRO */ + + /* Show fixed pixmap */ +#ifdef HAVE_CAIRO + cairo_identity_matrix(areawin->cr); + cairo_set_source(areawin->cr, areawin->fixed_pixmap); + cairo_paint(areawin->cr); +#else /* HAVE_CAIRO */ + XCopyArea(dpy, areawin->fixed_pixmap, areawin->window, areawin->gc, 0, 0, + areawin->width, areawin->height, 0, 0); +#endif /* HAVE_CAIRO */ + + areawin->redraw_ongoing = False; +} + +/*-------------------------------------------------------------------------*/ +/* Helper function for the xxx_mode_draw functions */ +/* Hide all the selected elements and draw all the element not currently */ +/* being edited to fixed_pixmap */ +/*-------------------------------------------------------------------------*/ + +static void draw_fixed_without_selection(void) +{ + int idx; + for (idx = 0; idx < areawin->selects; idx++) + SELTOGENERIC(&areawin->selectlist[idx])->type |= DRAW_HIDE; + draw_fixed(); + for (idx = 0; idx < areawin->selects; idx++) + SELTOGENERIC(&areawin->selectlist[idx])->type &= ~DRAW_HIDE; +} + +/*-------------------------------------------------------------------------*/ +/* generic xxx_mode_draw function, that handles most of the thing needed */ +/* for arcs, splines and paths. */ +/*-------------------------------------------------------------------------*/ + +static void generic_mode_draw(xcDrawType type, generic *newgen, + void (*decorations)(generic *newgen)) +{ + int idx; + + switch (type) { + case xcDRAW_INIT: + case xcREDRAW_FORCED: + draw_fixed_without_selection(); + /* fallthrough */ + + case xcDRAW_EDIT: + begin_event_mode_drawing(); + for (idx = 0; idx < areawin->selects; idx++) { + int scolor = SELTOCOLOR(&areawin->selectlist[idx]); + XcTopSetForeground(scolor); + easydraw(areawin->selectlist[idx], scolor); + } + if (decorations) + (*decorations)(newgen); + end_event_mode_drawing(); + break; + + case xcDRAW_FINAL: + begin_event_mode_drawing_final(); + for (idx = 0; idx < areawin->selects; idx++) { + int scolor = SELTOCOLOR(&areawin->selectlist[idx]); + XcTopSetForeground(scolor); + easydraw(areawin->selectlist[idx], scolor); + } + end_event_mode_drawing_final(); + if (areawin->selects > 1) /* FIXME: Temp. fix for multiple selects */ + areawin->redraw_needed = True; /* Will be removed later on */ + break; + + case xcDRAW_EMPTY: + /* Do not remove the empty begin/end. For cairo, this renders the */ + /* background with the fixed elements */ + begin_event_mode_drawing_final(); + end_event_mode_drawing_final(); + break; + } +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for ARC_MODE and EARC_MODE */ +/*-------------------------------------------------------------------------*/ + +static void arc_mode_decorations(generic *newgen) +{ + UDrawXLine(((arc*) newgen)->position, areawin->save); +} + +void arc_mode_draw(xcDrawType type, arc *newarc) +{ + generic_mode_draw(type, (generic*) newarc, arc_mode_decorations); +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for SPLINE_MODE and ESPLINE_MODE */ +/*-------------------------------------------------------------------------*/ + +static void spline_mode_decorations(generic *newgen) +{ + spline *newspline = (spline*) newgen; + UDrawXLine(newspline->ctrl[0], newspline->ctrl[1]); + UDrawXLine(newspline->ctrl[3], newspline->ctrl[2]); +} + +void spline_mode_draw(xcDrawType type, spline *newspline) +{ + generic_mode_draw(type, (generic*) newspline, spline_mode_decorations); +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for WIRE_MODE, BOX_MODE and EPOLY_MODE */ +/*-------------------------------------------------------------------------*/ + +void poly_mode_draw(xcDrawType type, polygon *newpoly) +{ + generic_mode_draw(type, (generic*) newpoly, NULL); +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for EPATH_MODE */ +/*-------------------------------------------------------------------------*/ + +static void path_mode_decorations(generic *newgen) +{ + genericptr *ggen; + path *newpath = (path*) newgen; + for (ggen = newpath->plist; ggen < newpath->plist + newpath->parts; ggen++) { + if (ELEMENTTYPE(*ggen) == SPLINE) { + spline *lastspline = TOSPLINE(ggen); + UDrawXLine(lastspline->ctrl[0], lastspline->ctrl[1]); + UDrawXLine(lastspline->ctrl[3], lastspline->ctrl[2]); + } + } +} + +void path_mode_draw(xcDrawType type, path *newpath) +{ + generic_mode_draw(type, (generic*) newpath, path_mode_decorations); +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for TEXT_MODE, CATTEXT_MODE and ETEXT_MODE */ +/*-------------------------------------------------------------------------*/ + +static void text_mode_decorations(generic *newgen) +{ + UDrawTLine((label*) newgen); +} + +void text_mode_draw(xcDrawType type, label *newlabel) +{ + generic_mode_draw(type, (generic*) newlabel, text_mode_decorations); +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for SELAREA_MODE */ +/*-------------------------------------------------------------------------*/ + +void selarea_mode_draw(xcDrawType type, void *unused) +{ + UNUSED(unused); + + switch (type) { + case xcREDRAW_FORCED: + draw_fixed(); + /* fallthrough */ + + case xcDRAW_INIT: + case xcDRAW_EDIT: + begin_event_mode_drawing(); + draw_all_selected(); + UDrawBox(areawin->origin, areawin->save); + end_event_mode_drawing(); + break; + + case xcDRAW_FINAL: + case xcDRAW_EMPTY: + /* No need for rendering the background, since it will be */ + /* overwritten by the select_area() function anyway */ + break; + } +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for RESCALE_MODE */ +/*-------------------------------------------------------------------------*/ + +void rescale_mode_draw(xcDrawType type, void *unused) +{ + UNUSED(unused); + + switch (type) { + case xcREDRAW_FORCED: + draw_fixed(); + /* fallthrough */ + + case xcDRAW_INIT: + case xcDRAW_EDIT: + begin_event_mode_drawing(); + UDrawRescaleBox(&areawin->save); + end_event_mode_drawing(); + break; + + case xcDRAW_FINAL: + case xcDRAW_EMPTY: + /* No need for rendering the background, since it will be */ + /* overwritten by the select_area() function anyway */ + break; + } +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for CATMOVE_MODE, MOVE_MODE and COPY_MODE */ +/*-------------------------------------------------------------------------*/ + +void move_mode_draw(xcDrawType type, void *unused) +{ + float wirewidth = xobjs.pagelist[areawin->page]->wirewidth; + short *selectobj; + genericptr *pgen; + int idx; + UNUSED(unused); + + switch (type) { + case xcREDRAW_FORCED: + case xcDRAW_INIT: + draw_fixed_without_selection(); + /* fallthrough */ + + case xcDRAW_EDIT: + begin_event_mode_drawing(); + XTopSetForeground(SELECTCOLOR); + for (idx = 0; idx < areawin->selects; idx++) + easydraw(areawin->selectlist[idx], DOFORALL); + for (selectobj = areawin->selectlist; selectobj < areawin->selectlist + + areawin->selects; selectobj++) { + if (SELECTTYPE(selectobj) == LABEL) { + label *labelobj = SELTOLABEL(selectobj); + if (labelobj->pin == False) + UDrawX(labelobj); + } + } + if (areawin->pinattach) { + for (pgen = topobject->plist; pgen < topobject->plist + + topobject->parts; pgen++) { + if (ELEMENTTYPE(*pgen) == POLYGON) { + polygon *cpoly = TOPOLY(pgen); + if (cpoly->cycle != NULL) + UDrawPolygon(cpoly, wirewidth); + } + } + } + end_event_mode_drawing(); + break; + + case xcDRAW_FINAL: + begin_event_mode_drawing_final(); + for (selectobj = areawin->selectlist; selectobj + < areawin->selectlist + areawin->selects; selectobj++) { + XTopSetForeground(SELTOCOLOR(selectobj)); + easydraw(*selectobj, DOFORALL); + } + end_event_mode_drawing_final(); + break; + + case xcDRAW_EMPTY: + /* Do not remove the empty begin/end. For cairo, this renders the */ + /* background with the fixed elements */ + begin_event_mode_drawing_final(); + end_event_mode_drawing_final(); + break; + } +} + +/*-------------------------------------------------------------------------*/ +/* Drawing function for ASSOC_MODE, EINST_MODE, (E)FONTCAT_MODE, PAN_MODE, */ +/* NORMAL_MODE, UNDO_MODE and CATALOG_MODE */ +/*-------------------------------------------------------------------------*/ + +void normal_mode_draw(xcDrawType type, void *unused) +{ + UNUSED(unused); + + switch (type) { + case xcDRAW_INIT: + case xcREDRAW_FORCED: + draw_fixed_without_selection(); + /* fallthrough */ + + case xcDRAW_EDIT: + begin_event_mode_drawing(); + + /* draw the highlighted netlist, if any */ + if (checkvalid(topobject) != -1) + if (topobject->highlight.netlist != NULL) + highlightnetlist(topobject, areawin->topinstance, 1); + + if ((areawin->selects == 1) && SELECTTYPE(areawin->selectlist) == LABEL + && areawin->textend > 0 && areawin->textpos > areawin->textend) { + labelptr drawlabel = SELTOLABEL(areawin->selectlist); + UDrawString(drawlabel, DOSUBSTRING, areawin->topinstance); + } + else if (eventmode == NORMAL_MODE || eventmode == CATALOG_MODE) + draw_all_selected(); + end_event_mode_drawing(); + break; + + case xcDRAW_FINAL: + break; + + case xcDRAW_EMPTY: + break; + } +} + + |