summaryrefslogtreecommitdiff
path: root/menucalls.c
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-10-20 17:43:57 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2018-10-20 17:43:57 +0200
commit04d5d0ea0f65a434e568fe031f6396caec9b3a8d (patch)
treedecc35c37120084c4a55311cb4e801524369ff57 /menucalls.c
Import Upstream version 3.8.78.dfsg
Diffstat (limited to 'menucalls.c')
-rw-r--r--menucalls.c1696
1 files changed, 1696 insertions, 0 deletions
diff --git a/menucalls.c b/menucalls.c
new file mode 100644
index 0000000..389049a
--- /dev/null
+++ b/menucalls.c
@@ -0,0 +1,1696 @@
+/*----------------------------------------------------------------------*/
+/* menucalls.c --- callback routines from the menu buttons, and */
+/* associated routines (either Tcl/Tk routines or */
+/* non-specific; Xt routines split off in file */
+/* xtfuncs.c 3/28/06) */
+/* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef XC_WIN32
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xutil.h>
+#endif
+
+#ifdef TCL_WRAPPER
+#include <tk.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local includes */
+/*----------------------------------------------------------------------*/
+
+#include "colordefs.h"
+#include "xcircuit.h"
+
+/*----------------------------------------------------------------------*/
+/* Function prototype declarations */
+/*----------------------------------------------------------------------*/
+#include "prototypes.h"
+
+/*----------------------------------------------------------------------*/
+/* External Variable definitions */
+/*----------------------------------------------------------------------*/
+
+extern char _STR2[250];
+extern char _STR[150]; /* Generic multipurpose string */
+extern xcWidget top;
+extern Display *dpy;
+extern Globaldata xobjs;
+extern XCWindowData *areawin;
+extern int *appcolors;
+extern int number_colors;
+extern colorindex *colorlist;
+extern ApplicationData appdata;
+extern Cursor appcursors[NUM_CURSORS];
+extern fontinfo *fonts;
+extern short fontcount;
+
+#ifdef TCL_WRAPPER
+extern Tcl_Interp *xcinterp;
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Local Variable definitions */
+/*----------------------------------------------------------------------*/
+
+u_short *fontnumbers;
+u_char nfontnumbers;
+
+/*----------------------------------------------*/
+/* Set Poly and Arc line styles and fill styles */
+/*----------------------------------------------*/
+
+#define BORDERS (NOBORDER | DOTTED | DASHED)
+#define ALLFILLS (FILLSOLID | FILLED)
+
+/*----------------------------------------------------------------*/
+/* setgrid, getgridspace are for grid and snap spacing sizes; */
+/* include routines to parse fractions */
+/*----------------------------------------------------------------*/
+
+void setgrid(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ float oscale, iscale = (float)xobjs.pagelist[areawin->page]->drawingscale.y /
+ (float)xobjs.pagelist[areawin->page]->drawingscale.x;
+ float fval;
+
+ /* For now, assume that the value is in the current display style. */
+ /* Might be nice in the future to make it accept any input. . . */
+
+ switch (xobjs.pagelist[areawin->page]->coordstyle) {
+ case INTERNAL:
+ if (sscanf(_STR2, "%f", &fval) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else *dataptr = fval / iscale;
+ break;
+ case CM:
+ oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
+ if (sscanf(_STR2, "%f", &fval) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ }
+ else *dataptr = fval * IN_CM_CONVERT / (iscale * oscale);
+ break;
+ case DEC_INCH: case FRAC_INCH: {
+ short parts;
+ char *sptr;
+ int f2, f3;
+
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ for (sptr = _STR2; *sptr != '\0'; sptr++)
+ if (*sptr == '/') *sptr = ' ';
+ parts = sscanf(_STR2, "%f %d %d", &fval, &f2, &f3);
+ if ((parts == 0) || (parts != 1 && (fval != (float)((int)fval)))) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ break;
+ }
+ if (parts == 2) fval /= (float)f2;
+ else if (parts == 3) fval += ((float)f2 / (float)f3);
+ *dataptr = fval * 72.0 / (iscale * oscale);
+ } break;
+ }
+ if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Write a measurement value into string "buffer" dependant on */
+/* the current default units of measure (centimeters or inches). */
+/*----------------------------------------------------------------*/
+
+void measurestr(float value, char *buffer)
+{
+ float oscale, iscale;
+ iscale = (float)(xobjs.pagelist[areawin->page]->drawingscale.y) /
+ (float)(xobjs.pagelist[areawin->page]->drawingscale.x);
+
+ switch (xobjs.pagelist[areawin->page]->coordstyle) {
+ case INTERNAL:
+ sprintf(buffer, "%5.3f", value * iscale);
+ break;
+ case CM:
+ oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
+ sprintf(buffer, "%5.3f cm", value * iscale * oscale / IN_CM_CONVERT);
+ break;
+ case DEC_INCH:
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ sprintf(buffer, "%5.3f in", value * iscale * oscale / 72.0);
+ break;
+ case FRAC_INCH:
+ oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
+ fraccalc(((value * iscale * oscale) / 72.0), buffer);
+ strcat(buffer, " in");
+ break;
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* set the global default line width. The unit used internally */
+/* is twice the value passed through pointer "dataptr". */
+/*----------------------------------------------------------------*/
+
+void setwidth(xcWidget w, float *dataptr)
+{
+ float oldvalue = *dataptr;
+ if (sscanf(_STR2, "%f", dataptr) == 0) {
+ *dataptr = oldvalue;
+ Wprintf("Illegal value");
+ return;
+ }
+ (*dataptr) *= 2.0;
+ if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
+}
+
+/*--------------------------------------------------------------*/
+/* Set text scale. */
+/*--------------------------------------------------------------*/
+
+void changetextscale(float newscale)
+{
+ short *osel;
+ labelptr settext;
+ stringpart *strptr, *nextptr;
+
+ /* In edit mode, add font scale change. */
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string, True,
+ areawin->topinstance)) {
+ undrawtext(settext);
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_SCALE)
+ strptr->data.scale = newscale;
+ else if (nextptr && nextptr->type == FONT_SCALE)
+ nextptr->data.scale = newscale;
+ else
+ labeltext(FONT_SCALE, (char *)&newscale);
+ redrawtext(settext);
+ }
+ else if (stringlength(settext->string, True, areawin->topinstance) > 0)
+ labeltext(FONT_SCALE, (char *)&newscale);
+ else (settext->scale = newscale);
+ }
+
+ /* Change scale on all selected text objects */
+
+ else if (areawin->selects > 0) {
+ float oldscale;
+ Boolean waschanged = FALSE;
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == LABEL) {
+ settext = SELTOLABEL(osel);
+ oldscale = settext->scale;
+ if (oldscale != newscale) {
+ undrawtext(settext);
+ settext->scale = newscale;
+ redrawtext(settext);
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ (genericptr)settext, (double)oldscale);
+ waschanged = TRUE;
+ }
+ }
+ }
+ if (waschanged) undo_finish_series();
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Auto-scale the drawing to fit the declared page size. */
+/* */
+/* If the page is declared encapsulated, then do nothing. */
+/* If a frame box is on the page, then scale to fit the frame */
+/* to the declared page size, not the whole object. */
+/*--------------------------------------------------------------*/
+
+void autoscale(int page)
+{
+ float newxscale, newyscale;
+ float scalefudge = (xobjs.pagelist[page]->coordstyle
+ == CM) ? CMSCALE : INCHSCALE;
+ int width, height;
+ polyptr framebox;
+
+ /* Check if auto-fit flag is selected */
+ if (!(xobjs.pagelist[page]->pmode & 2)) return;
+ /* Ignore auto-fit flag in EPS mode */
+ if (!(xobjs.pagelist[page]->pmode & 1)) return;
+
+ else if (topobject->bbox.width == 0 || topobject->bbox.height == 0) {
+ // Wprintf("Cannot auto-fit empty page");
+ return;
+ }
+
+ newxscale = (xobjs.pagelist[page]->pagesize.x -
+ (2 * xobjs.pagelist[page]->margins.x)) / scalefudge;
+ newyscale = (xobjs.pagelist[page]->pagesize.y -
+ (2 * xobjs.pagelist[page]->margins.y)) / scalefudge;
+
+ if ((framebox = checkforbbox(topobject)) != NULL) {
+ int i, minx, miny, maxx, maxy;
+
+ minx = maxx = framebox->points[0].x;
+ miny = maxy = framebox->points[0].y;
+ for (i = 1; i < framebox->number; i++) {
+ if (framebox->points[i].x < minx) minx = framebox->points[i].x;
+ else if (framebox->points[i].x > maxx) maxx = framebox->points[i].x;
+ if (framebox->points[i].y < miny) miny = framebox->points[i].y;
+ else if (framebox->points[i].y > maxy) maxy = framebox->points[i].y;
+ }
+ width = (maxx - minx);
+ height = (maxy - miny);
+ }
+ else {
+
+ width = toplevelwidth(areawin->topinstance, NULL);
+ height = toplevelheight(areawin->topinstance, NULL);
+ }
+
+ if (xobjs.pagelist[page]->orient == 0) { /* Portrait */
+ newxscale /= width;
+ newyscale /= height;
+ }
+ else {
+ newxscale /= height;
+ newyscale /= width;
+ }
+ xobjs.pagelist[page]->outscale = min(newxscale, newyscale);
+}
+
+/*--------------------------------------------------------------*/
+/* Parse a string for possible units of measure. Convert to */
+/* current units of measure, if necessary. Return the value */
+/* in current units, as a type float. */
+/*--------------------------------------------------------------*/
+
+float parseunits(char *strptr)
+{
+ short curtype;
+ Boolean inchunits = True;
+ float pv;
+ char units[12];
+
+ curtype = xobjs.pagelist[areawin->page]->coordstyle;
+
+ if (sscanf(strptr, "%f %11s", &pv, units) < 2)
+ return pv;
+ else {
+ if (!strncmp(units, "cm", 2) || !strncmp(units, "centimeters", 11))
+ inchunits = False;
+ switch(curtype) {
+ case CM:
+ return ((inchunits) ? (pv * 2.54) : pv);
+ default:
+ return ((inchunits) ? pv : (pv / 2.54));
+ }
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Set the output page size, in the current unit of measure */
+/* Return value: TRUE if _STR2 values were in inches, FALSE */
+/* if in centimeters. */
+/* XXX This API gives no good way to signal errors. */
+/*--------------------------------------------------------------*/
+
+Boolean setoutputpagesize(XPoint *dataptr)
+{
+ float px, py;
+ char units[10], *expos;
+#ifndef TCL_WRAPPER
+ Arg wargs[1];
+#endif
+
+ strcpy(units, "in");
+
+ if (sscanf(_STR2, "%f %*c %f %9s", &px, &py, units) < 4) {
+ if (sscanf(_STR2, "%f %*c %f", &px, &py) < 3) {
+ if ((expos = strchr(_STR2, 'x')) == NULL) {
+ Wprintf("Illegal Form for page size.");
+ return FALSE;
+ }
+ else {
+ *expos = '\0';
+ if (sscanf(_STR2, "%f", &px) == 0 ||
+ sscanf(expos + 1, "%f %9s", &py, units) == 0) {
+ Wprintf("Illegal Form for page size.");
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ /* Don't reduce page to less than the margins (1") or negative */
+ /* scales result. */
+
+ if ((px <= 2.0) || (py <= 2.0)) {
+ Wprintf("Page size too small for margins.");
+ return FALSE;
+ }
+
+ dataptr->x = (short)(px * 72.0);
+ dataptr->y = (short)(py * 72.0);
+
+ if (!strcmp(units, "cm")) {
+ dataptr->x /= 2.54;
+ dataptr->y /= 2.54;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------*/
+/* Get the text size (global or selected, depending on mode */
+/*--------------------------------------------------------------*/
+
+labelptr gettextsize(float **floatptr)
+{
+ labelptr settext = NULL;
+ short *osel;
+ stringpart *strptr, *nextptr;
+ const float f_one = 1.00;
+
+ if (floatptr) *floatptr = &areawin->textscale;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ settext = *((labelptr *)EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_SCALE) {
+ if (floatptr) *floatptr = &strptr->data.scale;
+ }
+ else if (nextptr && nextptr->type == FONT_SCALE) {
+ if (floatptr) *floatptr = &nextptr->data.scale;
+ }
+ else if (floatptr) *floatptr = (float *)(&f_one);
+ }
+ else {
+ settext = *((labelptr *)EDITPART);
+ if (floatptr) *floatptr = &(settext->scale);
+ }
+ }
+ else if (areawin->selects > 0) {
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == LABEL) {
+ settext = SELTOLABEL(osel);
+ if (floatptr) *floatptr = &(settext->scale);
+ break;
+ }
+ }
+ }
+ return settext;
+}
+
+/*--------------------------------------------------------------*/
+/* Set a character kern value */
+/*--------------------------------------------------------------*/
+
+void setkern(xcWidget w, stringpart *kpart)
+{
+ char *sptr;
+ short kd[2];
+
+ kd[0] = kd[1] = 0;
+
+ if ((sptr = strchr(_STR2, ',')) == NULL)
+ Wprintf("Use notation X,Y");
+ else {
+ *sptr = '\0';
+ sscanf(_STR2, "%hd", &kd[0]);
+ sscanf(sptr + 1, "%hd", &kd[1]);
+ if (kpart == NULL)
+ labeltext(KERN, (char *)kd);
+ else {
+ labelptr curlabel = TOLABEL(EDITPART);
+ undrawtext(curlabel);
+ kpart->data.kern[0] = kd[0];
+ kpart->data.kern[1] = kd[1];
+ redrawtext(curlabel);
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the drawing scale (specified as ratio X:Y) */
+/*----------------------------------------------------------------*/
+
+void setdscale(xcWidget w, XPoint *dataptr)
+{
+ char *sptr;
+
+ if ((sptr = strchr(_STR2, ':')) == NULL)
+ Wprintf("Use ratio X:Y");
+ else {
+ *sptr = '\0';
+ sscanf(_STR2, "%hd", &(dataptr->x));
+ sscanf(sptr + 1, "%hd", &(dataptr->y));
+ Wprintf("New scale is %hd:%hd", dataptr->x, dataptr->y);
+ W1printf(" ");
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the scale of an object or group of selected objects */
+/*----------------------------------------------------------------*/
+
+void setosize(xcWidget w, objinstptr dataptr)
+{
+ float tmpres, oldsize;
+ Boolean waschanged = FALSE;
+ short *osel;
+ objinstptr nsobj;
+ int res = sscanf(_STR2, "%f", &tmpres);
+
+ // Negative values are flips---deal with them independently
+
+ if (tmpres < 0)
+ tmpres = -tmpres;
+
+ if (res == 0 || tmpres == 0) {
+ Wprintf("Illegal value");
+ return;
+ }
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == OBJINST) {
+ nsobj = SELTOOBJINST(osel);
+ oldsize = nsobj->scale;
+ nsobj->scale = (oldsize < 0) ? -tmpres : tmpres;
+
+ if (oldsize != tmpres) {
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(osel), (double)oldsize);
+ waschanged = TRUE;
+ }
+ }
+ }
+ /* unselect_all(); */
+ if (waschanged) undo_finish_series();
+ pwriteback(areawin->topinstance);
+ drawarea(NULL, NULL, NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the linewidth of all selected arcs, polygons, splines, and */
+/* paths. */
+/*----------------------------------------------------------------*/
+
+void setwwidth(xcWidget w, void *dataptr)
+{
+ float tmpres, oldwidth;
+ short *osel;
+ arcptr nsarc;
+ polyptr nspoly;
+ splineptr nsspline;
+ pathptr nspath;
+
+ if (sscanf(_STR2, "%f", &tmpres) == 0) {
+ Wprintf("Illegal value");
+ return;
+ }
+ else if (areawin->selects == 0) {
+ areawin->linewidth = tmpres;
+ }
+ else {
+ for (osel = areawin->selectlist; osel < areawin->selectlist +
+ areawin->selects; osel++) {
+ if (SELECTTYPE(osel) == ARC) {
+ nsarc = SELTOARC(osel);
+ oldwidth = nsarc->width;
+ nsarc->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == POLYGON) {
+ nspoly = SELTOPOLY(osel);
+ oldwidth = nspoly->width;
+ nspoly->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == SPLINE) {
+ nsspline = SELTOSPLINE(osel);
+ oldwidth = nsspline->width;
+ nsspline->width = tmpres;
+ }
+ else if (SELECTTYPE(osel) == PATH) {
+ nspath = SELTOPATH(osel);
+ oldwidth = nspath->width;
+ nspath->width = tmpres;
+ }
+
+ if (oldwidth != tmpres)
+ register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(osel), (double)oldwidth);
+ }
+ unselect_all();
+ pwriteback(areawin->topinstance);
+ drawarea(NULL, NULL, NULL);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Add a new font name to the list of known fonts */
+/* Register the font number for the Alt-F cycling mechanism */
+/* Tcl: depends on command tag mechanism for GUI menu update. */
+/*--------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void makenewfontbutton()
+{
+ nfontnumbers++;
+ if (nfontnumbers == 1)
+ fontnumbers = (u_short *)malloc(sizeof(u_short));
+ else
+ fontnumbers = (u_short *)realloc(fontnumbers, nfontnumbers
+ * sizeof(u_short));
+ fontnumbers[nfontnumbers - 1] = fontcount - 1;
+}
+
+#endif /* TCL_WRAPPER */
+
+/*---------------------------------------------------------------*/
+/* Some Xcircuit routines using toggle and toggleexcl, */
+/* put here because they reference the menu structures directly. */
+/*---------------------------------------------------------------*/
+
+void setcolorscheme(Boolean boolvalue)
+{
+ if (boolvalue) {
+ PARAMCOLOR = appdata.parampix;
+ AUXCOLOR = appdata.auxpix;
+ OFFBUTTONCOLOR = appdata.buttonpix;
+ SELECTCOLOR = appdata.selectpix;
+ GRIDCOLOR = appdata.gridpix;
+ SNAPCOLOR = appdata.snappix;
+ AXESCOLOR = appdata.axespix;
+ BACKGROUND = appdata.bg;
+ FOREGROUND = appdata.fg;
+ }
+ else {
+ PARAMCOLOR = appdata.parampix2;
+ AUXCOLOR = appdata.auxpix2;
+ OFFBUTTONCOLOR = appdata.buttonpix2;
+ SELECTCOLOR = appdata.selectpix2;
+ GRIDCOLOR = appdata.gridpix2;
+ SNAPCOLOR = appdata.snappix2;
+ AXESCOLOR = appdata.axespix2;
+ BACKGROUND = appdata.bg2;
+ FOREGROUND = appdata.fg2;
+ }
+
+ BARCOLOR = appdata.barpix;
+ FILTERCOLOR = appdata.filterpix;
+
+ LOCALPINCOLOR = appdata.localcolor;
+ GLOBALPINCOLOR = appdata.globalcolor;
+ INFOLABELCOLOR = appdata.infocolor;
+ RATSNESTCOLOR = appdata.ratsnestcolor;
+ BBOXCOLOR = appdata.bboxpix;
+ CLIPMASKCOLOR = appdata.clipcolor;
+
+#if !defined(TCL_WRAPPER) && !defined(DOUBLEBUFFER)
+ {
+ Arg wargs[1];
+ XtSetArg(wargs[0], XtNbackground, BACKGROUND);
+ XtSetValues(areawin->area, wargs, 1);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Change menu selection for reported measurement units */
+/*----------------------------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void togglegrid(u_short type)
+{
+ static char *stylenames[] = {
+ "decimal inches",
+ "fractional inches",
+ "centimeters",
+ "internal units", NULL
+ };
+
+ XcInternalTagCall(xcinterp, 3, "config", "coordstyle", stylenames[type]);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*----------------------------------------------------------------*/
+/* Called by setgridtype() to complete setting the reported */
+/* measurement units */
+/*----------------------------------------------------------------*/
+
+void getgridtype(xcWidget button, pointertype value, caddr_t calldata)
+{
+ short oldtype = xobjs.pagelist[areawin->page]->coordstyle;
+ float scalefac = getpsscale(1.0, areawin->page) / INCHSCALE;
+
+#ifndef TCL_WRAPPER
+ togglegridstyles(button);
+#endif
+ xobjs.pagelist[areawin->page]->coordstyle = (short)value;
+
+ switch(value) {
+ case FRAC_INCH: case DEC_INCH: case INTERNAL:
+ if (oldtype == CM) {
+ xobjs.pagelist[areawin->page]->outscale *= scalefac;
+#ifndef TCL_WRAPPER
+ /* Note: Tcl defines a method for selecting standard */
+ /* page sizes. We really DON'T want to reset the size */
+ /* just because we switched measurement formats! */
+
+ xobjs.pagelist[areawin->page]->pagesize.x = 612;
+ xobjs.pagelist[areawin->page]->pagesize.y = 792; /* letter */
+#endif
+ }
+ break;
+ case CM:
+ if (oldtype != CM) {
+ xobjs.pagelist[areawin->page]->outscale *= scalefac;
+#ifndef TCL_WRAPPER
+ xobjs.pagelist[areawin->page]->pagesize.x = 595;
+ xobjs.pagelist[areawin->page]->pagesize.y = 842; /* A4 */
+#endif
+ }
+ break;
+ }
+ if (oldtype != xobjs.pagelist[areawin->page]->coordstyle) {
+ drawarea(NULL, NULL, NULL);
+ W1printf(" ");
+ }
+}
+
+/*------------------------------------------------------*/
+/* Make new library, add new button to the "Libraries" */
+/* cascaded menu, compose the library page, update the */
+/* library directory, and go to that library page. */
+/*------------------------------------------------------*/
+
+void newlibrary(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ int libnum = createlibrary(FALSE);
+ startcatalog(w, libnum, NULL);
+}
+
+/*----------------------------------------------*/
+/* Find an empty library, and return its page */
+/* number if it exists. Otherwise, return -1. */
+/* This search does not include the so-called */
+/* "User Library" (last library in list). */
+/*----------------------------------------------*/
+
+int findemptylib()
+{
+ int i;
+
+ for (i = 0; i < xobjs.numlibs - 1; i++) {
+ if (xobjs.userlibs[i].number == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*----------------------------------------------*/
+/* Make new page; goto that page */
+/* (wrapper for routine events.c:newpage()) */
+/*----------------------------------------------*/
+
+void newpagemenu(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ newpage((short)value);
+}
+
+#ifdef TCL_WRAPPER
+
+/*----------------------------------------------*/
+/* Make new library and add a new button to the */
+/* "Libraries" cascaded menu. */
+/*----------------------------------------------*/
+
+int createlibrary(Boolean force)
+{
+ /* xcWidget libmenu, newbutton, oldbutton; (jdk) */
+#ifndef TCL_WRAPPER
+ Arg wargs[2];
+#endif
+ /* char libstring[20]; (jdk) */
+ int libnum;
+ objectptr newlibobj;
+
+ /* If there's an empty library, return its number */
+ if ((!force) && (libnum = findemptylib()) >= 0) return (libnum + LIBRARY);
+ libnum = (xobjs.numlibs++) + LIBRARY;
+ xobjs.libtop = (objinstptr *)realloc(xobjs.libtop,
+ (libnum + 1) * sizeof(objinstptr));
+ xobjs.libtop[libnum] = xobjs.libtop[libnum - 1];
+ libnum--;
+
+ newlibobj = (objectptr) malloc(sizeof(object));
+ initmem(newlibobj);
+ xobjs.libtop[libnum] = newpageinst(newlibobj);
+
+ sprintf(newlibobj->name, "Library %d", libnum - LIBRARY + 1);
+
+ /* Create the library */
+
+ xobjs.userlibs = (Library *) realloc(xobjs.userlibs, xobjs.numlibs
+ * sizeof(Library));
+ xobjs.userlibs[libnum + 1 - LIBRARY] = xobjs.userlibs[libnum - LIBRARY];
+ xobjs.userlibs[libnum - LIBRARY].library = (objectptr *) malloc(sizeof(objectptr));
+ xobjs.userlibs[libnum - LIBRARY].number = 0;
+ xobjs.userlibs[libnum - LIBRARY].instlist = NULL;
+
+ sprintf(_STR2, "xcircuit::newlibrarybutton \"%s\"", newlibobj->name);
+ Tcl_Eval(xcinterp, _STR2);
+
+ /* Update the library directory to include the new page */
+
+ composelib(LIBLIB);
+
+ return libnum;
+}
+
+/*--------------------------------------------------------------*/
+/* Routine called by newpage() if new button needs to be made */
+/* to add to the "Pages" cascaded menu. */
+/*--------------------------------------------------------------*/
+
+void makepagebutton()
+{
+ /* xcWidget pagemenu, newbutton; (jdk) */
+ /* char pagestring[10]; (jdk) */
+
+ /* make new entry in the menu */
+
+ sprintf(_STR2, "newpagebutton \"Page %d\"", xobjs.pages);
+ Tcl_Eval(xcinterp, _STR2);
+
+ /* Update the page directory */
+
+ composelib(PAGELIB);
+}
+
+/*----------------------------------------------------------------*/
+/* Find the Page menu button associated with the page number */
+/* (passed parameter) and set the label of that button to the */
+/* object name (= page label) */
+/*----------------------------------------------------------------*/
+
+void renamepage(short pagenumber)
+{
+ objinstptr thisinst = xobjs.pagelist[pagenumber]->pageinst;
+ char *pname, *plabel;
+
+ if ((pagenumber >= 0) && (pagenumber < xobjs.pages - 1) &&
+ (thisinst != NULL)) {
+ plabel = thisinst->thisobject->name;
+ pname = (char *)malloc(28 + strlen(plabel));
+ sprintf(pname, "xcircuit::renamepage %d {%s}", pagenumber + 1, plabel);
+ Tcl_Eval(xcinterp, pname);
+ free(pname);
+ }
+}
+
+/*--------------------------------------------------------------*/
+/* Same routine as above, for Library page menu buttons */
+/*--------------------------------------------------------------*/
+
+void renamelib(short libnumber)
+{
+ if (libnumber <= xobjs.numlibs) return;
+
+ sprintf(_STR2, "xcircuit::renamelib %d \"%s\"", libnumber - LIBRARY + 1,
+ xobjs.libtop[libnumber]->thisobject->name);
+ Tcl_Eval(xcinterp, _STR2);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the color menu */
+/*--------------------------------------------------------------*/
+
+void setcolormark(int colorval)
+{
+ /* Set GUI variables and execute any command tags associated */
+ /* with the "color" command */
+
+ char cstr[6];
+ int i;
+
+ if (colorval != DEFAULTCOLOR) {
+ for (i = 0; i < number_colors; i++)
+ if (colorlist[i].color.pixel == colorval) {
+ sprintf(cstr, "%5d", i);
+ break;
+ }
+ }
+
+#ifdef TCL_WRAPPER
+ XcInternalTagCall(xcinterp, 3, "color", "set", (colorval == DEFAULTCOLOR) ?
+ "inherit" : cstr);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Set the checkmarks on the element styles menu */
+/*----------------------------------------------------------------*/
+
+void setallstylemarks(u_short styleval)
+{
+ /* Execute any command tags associated */
+ /* with the "fill" and "border" commands. */
+
+ char fstr[10];
+ int fillfactor;
+ const char *bptr;
+
+ const char *borders[] = {"solid", "unbordered", "dashed", "dotted", NULL};
+ enum BorderIdx { SolidIdx, UnborderedIdx, DashedIdx, DottedIdx };
+
+ if (styleval & FILLED) {
+ fillfactor = (int)(12.5 * (float)(1 + ((styleval & FILLSOLID) >> 5)));
+ if (fillfactor < 100)
+ sprintf(fstr, "%d", fillfactor);
+ else
+ strcpy(fstr, "solid");
+ }
+ else
+ strcpy(fstr, "unfilled");
+
+ switch (styleval & BORDERS) {
+ case DASHED:
+ bptr = borders[DashedIdx];
+ break;
+ case DOTTED:
+ bptr = borders[DottedIdx];
+ break;
+ case NOBORDER:
+ bptr = borders[UnborderedIdx];
+ break;
+ default:
+ bptr = borders[SolidIdx];
+ break;
+ }
+
+ XcInternalTagCall(xcinterp, 3, "fill", fstr,
+ (styleval & OPAQUE) ? "opaque" : "transparent");
+ XcInternalTagCall(xcinterp, 3, "border", "bbox", (styleval & BBOX) ? "true" :
+ "false");
+ XcInternalTagCall(xcinterp, 3, "border", "clipmask", (styleval & CLIPMASK) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 2, "border", (styleval & UNCLOSED) ? "unclosed" :
+ "closed");
+ XcInternalTagCall(xcinterp, 2, "border", bptr);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Check for a bounding box polygon */
+/*--------------------------------------------------------------*/
+
+polyptr checkforbbox(objectptr localdata)
+{
+ polyptr *cbbox;
+
+ for (cbbox = (polyptr *)localdata->plist; cbbox <
+ (polyptr *)localdata->plist + localdata->parts; cbbox++)
+ if (IS_POLYGON(*cbbox))
+ if ((*cbbox)->style & BBOX) return *cbbox;
+
+ return NULL;
+}
+
+/*--------------------------------------------------------------*/
+/* Set a value for element style. "Mask" determines the bits */
+/* to be affected, so that "value" may turn bits either on or */
+/* off. */
+/*--------------------------------------------------------------*/
+
+int setelementstyle(xcWidget w, u_short value, u_short mask)
+{
+ Boolean preselected, selected = False;
+ short *sstyle;
+ u_short newstyle, oldstyle;
+
+ if (areawin->selects == 0) {
+ preselected = FALSE;
+ if (value & BBOX)
+ checkselect(POLYGON);
+ else
+ checkselect(ARC | SPLINE | POLYGON | PATH);
+ }
+ else preselected = TRUE;
+
+ if (areawin->selects > 0) {
+ if (value & BBOX) {
+ polyptr ckp;
+ if (areawin->selects != 1) {
+ Wprintf("Choose only one polygon to be the bounding box");
+ return -1;
+ }
+ else if (SELECTTYPE(areawin->selectlist) != POLYGON) {
+ Wprintf("Bounding box can only be a polygon");
+ return -1;
+ }
+ else if (((ckp = checkforbbox(topobject)) != NULL) &&
+ (ckp != SELTOPOLY(areawin->selectlist))) {
+ Wprintf("Only one bounding box allowed per page");
+ return -1;
+ }
+ }
+
+ for (sstyle = areawin->selectlist; sstyle < areawin->selectlist
+ + areawin->selects; sstyle++) {
+ short stype = SELECTTYPE(sstyle);
+ if (stype & (ARC | POLYGON | SPLINE | PATH)) {
+ short *estyle;
+ switch (stype) {
+ case ARC:
+ estyle = &((SELTOARC(sstyle))->style);
+ break;
+ case SPLINE:
+ estyle = &((SELTOSPLINE(sstyle))->style);
+ break;
+ case POLYGON:
+ estyle = &((SELTOPOLY(sstyle))->style);
+ break;
+ case PATH:
+ estyle = &((SELTOPATH(sstyle))->style);
+ break;
+ }
+ oldstyle = newstyle = *estyle;
+ newstyle &= ~(mask);
+ newstyle |= value;
+
+ if (oldstyle != newstyle) {
+ if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
+ Wprintf("Must have either a border or filler");
+ continue;
+ }
+
+ XSetFunction(dpy, areawin->gc, GXcopy);
+ XSetForeground(dpy, areawin->gc, BACKGROUND);
+ easydraw(*sstyle, DOFORALL);
+
+ *estyle = newstyle;
+ if (mask & BBOX)
+ (SELTOPOLY(sstyle))->color = (value & BBOX) ? BBOXCOLOR
+ : DEFAULTCOLOR;
+
+ XSetFunction(dpy, areawin->gc, GXxor);
+ XSetForeground(dpy, areawin->gc, SELECTCOLOR ^ BACKGROUND);
+ easydraw(*sstyle, DOFORALL);
+
+#ifdef TCL_WRAPPER
+ register_for_undo(XCF_ChangeStyle,
+ (sstyle == areawin->selectlist + areawin->selects - 1) ?
+ UNDO_DONE : UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(sstyle), (int)oldstyle);
+#else
+ /* Tcl version differs in that the element is not deselected after */
+
+ register_for_undo(XCF_ChangeStyle, UNDO_MORE, areawin->topinstance,
+ SELTOGENERIC(sstyle), (int)oldstyle);
+#endif
+ }
+ selected = True;
+ }
+ }
+ }
+ if (selected)
+ pwriteback(areawin->topinstance);
+ else {
+ newstyle = areawin->style;
+ if (value & BBOX) {
+ Wprintf("Cannot set default style to Bounding Box");
+ newstyle &= ~(BBOX);
+ return -1;
+ }
+ else if (value & CLIPMASK) {
+ Wprintf("Cannot set default style to Clip Mask");
+ newstyle &= ~(CLIPMASK);
+ return -1;
+ }
+ else {
+ newstyle &= ~mask;
+ newstyle |= value;
+ }
+
+ if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
+ Wprintf("Must have either a border or filler");
+ return -1;
+ }
+ areawin->style = newstyle;
+#ifndef TCL_WRAPPER
+ overdrawpixmap(w);
+#endif
+ }
+#ifndef TCL_WRAPPER
+ setallstylemarks(newstyle);
+#endif
+ if (!preselected)
+ unselect_all();
+
+ return (int)newstyle;
+}
+
+/*-----------------------------------------------*/
+/* Set the color value for all selected elements */
+/*-----------------------------------------------*/
+
+#ifdef TCL_WRAPPER
+
+void setcolor(xcWidget w, int cindex)
+{
+ short *scolor;
+ int *ecolor, cval, oldcolor;
+ Boolean selected = False;
+ stringpart *strptr, *nextptr;
+
+ if (cindex == -1) cval = -1;
+ else cval = colorlist[cindex].color.pixel;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ labelptr curlabel = TOLABEL(EDITPART);
+ strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
+ areawin->topinstance);
+ nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
+ areawin->topinstance);
+ if (strptr && strptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ strptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else if (nextptr && nextptr->type == FONT_COLOR) {
+ undrawtext(curlabel);
+ nextptr->data.color = cindex;
+ redrawtext(curlabel);
+ }
+ else {
+ sprintf(_STR2, "%d", cindex);
+ labeltext(FONT_COLOR, (char *)&cindex);
+ }
+ }
+
+ else if (areawin->selects > 0) {
+ for (scolor = areawin->selectlist; scolor < areawin->selectlist
+ + areawin->selects; scolor++) {
+ ecolor = &(SELTOCOLOR(scolor));
+ oldcolor = *ecolor;
+ *ecolor = cval;
+ selected = True;
+
+ register_for_undo(XCF_Color, (scolor == areawin->selectlist
+ + areawin->selects - 1) ? UNDO_DONE : UNDO_MORE,
+ areawin->topinstance,
+ SELTOGENERIC(scolor), (int)oldcolor);
+ }
+ }
+
+ setcolormark(cval);
+ if (!selected) {
+ if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE)
+ areawin->color = cval;
+ }
+ else pwriteback(areawin->topinstance);
+}
+
+/*--------------------------------------------------------------*/
+/* Set the menu checkmarks on the font menu */
+/*--------------------------------------------------------------*/
+
+void togglefontmark(int fontval)
+{
+ if (fonts[fontval].family != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "family", fonts[fontval].family);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label style menu */
+/* fvalue is for font, jvalue is for justification */
+/*------------------------------------------------------*/
+
+void togglestylemark(int styleval)
+{
+ char *cstyle = translatestyle(styleval);
+ if (cstyle != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "style", cstyle);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label encoding menu */
+/*------------------------------------------------------*/
+
+void toggleencodingmark(int encodingval)
+{
+ char *cenc = translateencoding(encodingval);
+ if (cenc != NULL)
+ XcInternalTagCall(xcinterp, 3, "label", "encoding", cenc);
+}
+
+/*------------------------------------------------------*/
+/* Set checkmarks on label justification & flags menu */
+/*------------------------------------------------------*/
+
+void togglejustmarks(int justvalue)
+{
+ XcInternalTagCall(xcinterp, 4, "label", "justify", (justvalue & RIGHT) ? "right" :
+ (justvalue & NOTLEFT) ? "center" : "left",
+ (justvalue & TOP) ? "top" : (justvalue & NOTBOTTOM) ? "middle" : "bottom");
+ XcInternalTagCall(xcinterp, 3, "label", "flipinvariant", (justvalue & FLIPINV) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 3, "label", "latex", (justvalue & LATEXLABEL) ?
+ "true" : "false");
+ XcInternalTagCall(xcinterp, 3, "label", "visible", (justvalue & PINVISIBLE) ?
+ "true" : "false");
+}
+
+/*-------------------------------------------------------------*/
+/* Simultaneously set all relevant checkmarks for a text label */
+/*-------------------------------------------------------------*/
+
+void setfontmarks(short fvalue, short jvalue)
+{
+ if ((fvalue >= 0) && (fvalue < fontcount)) {
+ toggleencodingmark(fvalue);
+ togglestylemark(fvalue);
+ togglefontmark(fvalue);
+ }
+ togglejustmarks(jvalue);
+}
+
+#endif /* TCL_WRAPPER */
+
+/*--------------------------------------------------------------*/
+/* Parameterize a label string (wrapper for parameterize()). */
+/* Assumes that the name has been generated by the popup prompt */
+/* and is therefore held in variable _STR2 */
+/*--------------------------------------------------------------*/
+
+void stringparam(xcWidget w, caddr_t clientdata, caddr_t calldata)
+{
+ genericptr *settext;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = (genericptr *)EDITPART;
+ makeparam(TOLABEL(settext), _STR2);
+ unselect_all();
+ setparammarks(NULL);
+ }
+ else if (checkselect(LABEL)) parameterize(P_SUBSTRING, _STR2, -1);
+}
+
+/*--------------------------------------------------------------*/
+/* Numerical parameterization (wrapper for parameterize()). */
+/*--------------------------------------------------------------*/
+
+void startparam(xcWidget w, pointertype value, caddr_t calldata)
+{
+ if (value == (pointertype)P_SUBSTRING) {
+ strcpy(_STR2, (calldata != NULL) ? (char *)calldata : "substring");
+ stringparam(w, NULL, NULL);
+ }
+ else if ((eventmode != NORMAL_MODE) || (areawin->selects > 0))
+ parameterize((int)value, (char *)calldata, -1);
+}
+
+/*---------------------------------------------------------------*/
+/* Unparameterize a label string (wrapper for unparameterize()). */
+/*---------------------------------------------------------------*/
+
+void startunparam(xcWidget w, pointertype value, caddr_t calldata)
+{
+ if (areawin->selects > 0)
+ unparameterize((int)value);
+ unselect_all();
+ setparammarks(NULL);
+}
+
+/*----------------------------------------------------------------*/
+/* Set checkmarks on font menu according to the global defaults */
+/*----------------------------------------------------------------*/
+
+void setdefaultfontmarks()
+{
+ setfontmarks(areawin->psfont, areawin->justify);
+}
+
+/*----------------------------------------------------------------*/
+/* Pick up font name from _STR2 and pass it to loadfontfile() */
+/*----------------------------------------------------------------*/
+
+void locloadfont(xcWidget w, char *value)
+{
+ loadfontfile(_STR2);
+ free(value);
+}
+
+/*----------------------------------------------------------------*/
+/* Find the best matching font given new font, style, or encoding */
+/*----------------------------------------------------------------*/
+/* newfont, style, or encoding = -1 when not applicable */
+/* Return the number of the best matching font. */
+/*----------------------------------------------------------------*/
+
+short findbestfont(short curfont, short newfont, short style, short encoding) {
+
+ char *newfamily;
+ short i, newstyle, newenc;
+
+ if (fontcount == 0) return -1;
+ if (curfont < 0) curfont = 0;
+
+ if (newfont < 0)
+ newfamily = fonts[curfont].family;
+ else if (newfont >= fontcount) { /* move to next font family */
+ short newidx;
+ newfont = 0;
+ while (strcmp(fonts[fontnumbers[newfont]].family, fonts[curfont].family))
+ newfont++;
+ newidx = (newfont + 1) % nfontnumbers;
+ while (!strcmp(fonts[curfont].family, fonts[fontnumbers[newidx]].family) &&
+ newfont != newidx)
+ newidx = (newidx + 1) % nfontnumbers;
+ newfamily = fonts[fontnumbers[newidx]].family;
+ newfont = fontnumbers[newidx];
+ }
+ else
+ newfamily = fonts[newfont].family;
+
+ if (style < 0)
+ newstyle = fonts[curfont].flags & 0x03;
+ else
+ newstyle = style & 0x03;
+
+ if (encoding < 0)
+ newenc = fonts[curfont].flags & 0xf80;
+ else
+ newenc = encoding << 7;
+
+ /* Best position is a match on all conditions */
+
+ for (i = 0; i < fontcount; i++)
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ ((fonts[i].flags & 0x03) == newstyle) &&
+ ((fonts[i].flags & 0xf80) == newenc))
+ return i;
+
+ /* Fallback position 1: Match requested property and one other. */
+ /* order of preference: */
+ /* Requested property Priority 1 Priority 2 */
+ /* Font Style Encoding */
+ /* Style Font (none) */
+ /* Encoding Font (none) */
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ (fonts[i].flags & 0x03) == newstyle) return i;
+ }
+ else if (style >= 0) {
+ if (((fonts[i].flags & 0x03) == newstyle) &&
+ (!strcmp(fonts[i].family, newfamily))) return i;
+ }
+ else if (encoding >= 0) {
+ if (((fonts[i].flags & 0xf80) == newenc) &&
+ (!strcmp(fonts[i].family, newfamily))) return i;
+ }
+ }
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if ((!strcmp(fonts[i].family, newfamily)) &&
+ ((fonts[i].flags & 0xf80) >> 7) == newenc) return i;
+ }
+ }
+
+ /* Fallback position 2: Match only the requested property. */
+ /* For font selection only: Don't want to select a new font */
+ /* just because a certain style or encoding wasn't available.*/
+
+ for (i = 0; i < fontcount; i++) {
+ if (newfont >= 0) {
+ if (!strcmp(fonts[i].family, newfamily)) return i;
+ }
+ }
+
+ /* Failure to find matching font property */
+
+ if (style >= 0) {
+ Wprintf("Font %s not available in this style", newfamily);
+ }
+ else {
+ Wprintf("Font %s not available in this encoding", newfamily);
+ }
+ return (-1);
+}
+
+/*----------------------------------------------------------------*/
+/* Set the font. This depends on the system state as to whether */
+/* font is set at current position in label, for an entire label, */
+/* or as the default font to begin new labels. */
+/*----------------------------------------------------------------*/
+
+void setfontval(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+ i = findbestfont(tc, (short)value, -1, -1);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+ togglefontmark(i);
+ }
+ }
+ return;
+ }
+ }
+
+ /* otherwise, look for the last style used in the string */
+ tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ /* Font change command will always find a value since at least one */
+ /* font has to exist for the font menu button to exist. */
+
+ if ((newfont = (int)findbestfont(tc, (short)value, -1, -1)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+
+ if (w != NULL) togglefontmark(newfont);
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontval() */
+/*----------------------------------------------------------------*/
+
+void setfont(xcWidget w, pointertype value, caddr_t calldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontval(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontval(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontval(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the style (bold, italic, normal) for the font, similarly */
+/* to the above routine setfontval(). */
+/*----------------------------------------------------------------*/
+
+void setfontstyle(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+
+ /* find font which matches family and style, if available */
+
+ i = findbestfont(tc, -1, (short)value, -1);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+#ifndef TCL_WRAPPER
+ togglefontstyles(w);
+#endif
+ }
+ }
+ return;
+ }
+ }
+
+ /* Otherwise, look for the last font used in the string */
+ /* Fix by Dimitri Princen. Was areawin->textpos - 2; was there a */
+ /* reason for that? */
+
+ tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ if ((newfont = (int)findbestfont(tc, -1, (short)value, -1)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+#ifdef TCL_WRAPPER
+ toggleencodingmark(value);
+#else
+ togglefontstyles(w);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontstyle() */
+/*----------------------------------------------------------------*/
+
+void fontstyle(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontstyle(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontstyle(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontstyle(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------------------------*/
+/* Set the encoding (standard, ISO-Latin1, special) for the font, */
+/* similarly to the above routine setfontval(). */
+/*----------------------------------------------------------------*/
+
+void setfontencoding(xcWidget w, pointertype value, labelptr settext)
+{
+ int newfont;
+ short i, tc;
+ stringpart *strptr;
+
+ if (settext != NULL) {
+
+ /* if last byte was a font designator, use it */
+
+ if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
+ True, areawin->topinstance)) {
+ strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
+ areawin->topinstance);
+ if (strptr->type == FONT_NAME) {
+ tc = strptr->data.font;
+
+ i = findbestfont(tc, -1, -1, (short)value);
+ if (i >= 0) {
+ undrawtext(settext);
+ strptr->data.font = i;
+ redrawtext(settext);
+ if (w != NULL) {
+ charreport(settext);
+#ifdef TCL_WRAPPER
+ toggleencodingmark(value);
+#else
+ toggleencodings(w);
+#endif
+ }
+ }
+ return;
+ }
+ }
+
+ /* otherwise, look for the last style used in the string */
+ tc = findcurfont(areawin->textpos - 2, settext->string, areawin->topinstance);
+ }
+ else tc = areawin->psfont;
+
+ if ((newfont = (int)findbestfont(tc, -1, -1, (short)value)) < 0) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ Wprintf("Font is now %s", fonts[newfont].psname);
+ sprintf(_STR2, "%d", newfont);
+ labeltext(FONT_NAME, (char *)&newfont);
+ }
+ else {
+ Wprintf("Default font is now %s", fonts[newfont].psname);
+ areawin->psfont = newfont;
+ }
+
+#ifndef TCL_WRAPPER
+ toggleencodings(w);
+#endif
+}
+
+/*----------------------------------------------------------------*/
+/* Wrapper for routine setfontencoding() */
+/*----------------------------------------------------------------*/
+
+void fontencoding(xcWidget w, pointertype value, caddr_t nulldata)
+{
+ short *fselect;
+ labelptr settext;
+ short labelcount = 0;
+ Boolean preselected;
+
+ if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
+ eventmode == EFONTCAT_MODE) return;
+
+ if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
+ settext = *((labelptr *)EDITPART);
+ setfontencoding(w, value, settext);
+ charreport(settext);
+ }
+ else {
+ if (areawin->selects == 0) {
+ checkselect(LABEL);
+ preselected = FALSE;
+ }
+ else preselected = TRUE;
+ areawin->textpos = 1;
+ for (fselect = areawin->selectlist; fselect < areawin->selectlist +
+ areawin->selects; fselect++) {
+ if (SELECTTYPE(fselect) == LABEL) {
+ labelcount++;
+ settext = SELTOLABEL(fselect);
+ setfontencoding(NULL, value, settext);
+ }
+ }
+ if (labelcount == 0) setfontencoding(w, value, NULL);
+ else if (!preselected) unselect_all();
+ }
+}
+
+/*----------------------------------------------*/
+/* Generate the table of special characters */
+/* */
+/* Return FALSE if the edited label is LaTeX- */
+/* compatible, since LaTeX text does not */
+/* usually contain special characters, but it */
+/* does contain a lot of backslashes. */
+/*----------------------------------------------*/
+
+Boolean dospecial()
+{
+ labelptr curlabel;
+ int cfont;
+
+ curlabel = TOLABEL(EDITPART);
+ if (curlabel->justify & LATEXLABEL) return False;
+
+ cfont = findcurfont(areawin->textpos, curlabel->string, areawin->topinstance);
+ composefontlib(cfont);
+ startcatalog(NULL, FONTLIB, NULL);
+ return True;
+}
+
+/*-------------------------------------------------------------------------*/