diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2018-10-20 17:43:57 +0200 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2018-10-20 17:43:57 +0200 |
commit | 04d5d0ea0f65a434e568fe031f6396caec9b3a8d (patch) | |
tree | decc35c37120084c4a55311cb4e801524369ff57 /menucalls.c |
Import Upstream version 3.8.78.dfsg
Diffstat (limited to 'menucalls.c')
-rw-r--r-- | menucalls.c | 1696 |
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; +} + +/*-------------------------------------------------------------------------*/ |