summaryrefslogtreecommitdiff
path: root/elements.c
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-10-20 17:54:38 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2018-10-20 17:54:38 +0200
commit69fcfa5f570e247c58cbc35eb48c5e55eaaa4c8e (patch)
tree6e8aa19578c2657cad60c3969d9018c4c4a9584a /elements.c
parent332f65d9afdb5cb8e4d62883ad522f430ab39208 (diff)
parentca2442640f4394296d9d6b0c42d41d399dbf9667 (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.c634
1 files changed, 534 insertions, 100 deletions
diff --git a/elements.c b/elements.c
index 7187691..ec50433 100644
--- a/elements.c
+++ b/elements.c
@@ -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;
+ }
+}
+
+