Corrected a long-standing error in which ending text with a literal
[xcircuit.git] / menucalls.c
blob22ebe6695534335a8f62ffd821222739b3d66e33
1 /*----------------------------------------------------------------------*/
2 /* menucalls.c --- callback routines from the menu buttons, and */
3 /* associated routines (either Tcl/Tk routines or */
4 /* non-specific; Xt routines split off in file */
5 /* xtfuncs.c 3/28/06) */
6 /* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
7 /*----------------------------------------------------------------------*/
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <sys/types.h>
14 #include <errno.h>
15 #include <limits.h>
17 #ifndef XC_WIN32
18 #include <X11/Intrinsic.h>
19 #include <X11/StringDefs.h>
20 #include <X11/Xutil.h>
21 #endif
23 #ifdef TCL_WRAPPER
24 #include <tk.h>
25 #endif
27 /*----------------------------------------------------------------------*/
28 /* Local includes */
29 /*----------------------------------------------------------------------*/
31 #include "colordefs.h"
32 #include "xcircuit.h"
34 /*----------------------------------------------------------------------*/
35 /* Function prototype declarations */
36 /*----------------------------------------------------------------------*/
37 #include "prototypes.h"
39 /*----------------------------------------------------------------------*/
40 /* External Variable definitions */
41 /*----------------------------------------------------------------------*/
43 extern char _STR2[250];
44 extern char _STR[150]; /* Generic multipurpose string */
45 extern xcWidget top;
46 extern Display *dpy;
47 extern Globaldata xobjs;
48 extern XCWindowData *areawin;
49 extern int number_colors;
50 extern colorindex *colorlist;
51 extern ApplicationData appdata;
52 extern Cursor appcursors[NUM_CURSORS];
53 extern fontinfo *fonts;
54 extern short fontcount;
56 #ifdef TCL_WRAPPER
57 extern Tcl_Interp *xcinterp;
58 #endif
60 /*----------------------------------------------------------------------*/
61 /* Local Variable definitions */
62 /*----------------------------------------------------------------------*/
64 u_short *fontnumbers;
65 u_char nfontnumbers;
67 /*----------------------------------------------*/
68 /* Set Poly and Arc line styles and fill styles */
69 /*----------------------------------------------*/
71 #define BORDERS (NOBORDER | DOTTED | DASHED)
72 #define ALLFILLS (FILLSOLID | FILLED)
74 /*----------------------------------------------------------------*/
75 /* setgrid, getgridspace are for grid and snap spacing sizes; */
76 /* include routines to parse fractions */
77 /*----------------------------------------------------------------*/
79 void setgrid(xcWidget w, float *dataptr)
81 float oldvalue = *dataptr;
82 float oscale, iscale = (float)xobjs.pagelist[areawin->page]->drawingscale.y /
83 (float)xobjs.pagelist[areawin->page]->drawingscale.x;
84 float fval;
86 /* For now, assume that the value is in the current display style. */
87 /* Might be nice in the future to make it accept any input. . . */
89 switch (xobjs.pagelist[areawin->page]->coordstyle) {
90 case INTERNAL:
91 if (sscanf(_STR2, "%f", &fval) == 0) {
92 *dataptr = oldvalue;
93 Wprintf("Illegal value");
95 else *dataptr = fval / iscale;
96 break;
97 case CM:
98 oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
99 if (sscanf(_STR2, "%f", &fval) == 0) {
100 *dataptr = oldvalue;
101 Wprintf("Illegal value");
103 else *dataptr = fval * IN_CM_CONVERT / (iscale * oscale);
104 break;
105 case DEC_INCH: case FRAC_INCH: {
106 short parts;
107 char *sptr;
108 int f2, f3;
110 oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
111 for (sptr = _STR2; *sptr != '\0'; sptr++)
112 if (*sptr == '/') *sptr = ' ';
113 parts = sscanf(_STR2, "%f %d %d", &fval, &f2, &f3);
114 if ((parts == 0) || (parts != 1 && (fval != (float)((int)fval)))) {
115 *dataptr = oldvalue;
116 Wprintf("Illegal value");
117 break;
119 if (parts == 2) fval /= (float)f2;
120 else if (parts == 3) fval += ((float)f2 / (float)f3);
121 *dataptr = fval * 72.0 / (iscale * oscale);
122 } break;
124 if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
127 /*----------------------------------------------------------------*/
128 /* Write a measurement value into string "buffer" dependant on */
129 /* the current default units of measure (centimeters or inches). */
130 /*----------------------------------------------------------------*/
132 void measurestr(float value, char *buffer)
134 float oscale, iscale;
135 iscale = (float)(xobjs.pagelist[areawin->page]->drawingscale.y) /
136 (float)(xobjs.pagelist[areawin->page]->drawingscale.x);
138 switch (xobjs.pagelist[areawin->page]->coordstyle) {
139 case INTERNAL:
140 sprintf(buffer, "%5.3f", value * iscale);
141 break;
142 case CM:
143 oscale = xobjs.pagelist[areawin->page]->outscale * CMSCALE;
144 sprintf(buffer, "%5.3f cm", value * iscale * oscale / IN_CM_CONVERT);
145 break;
146 case DEC_INCH:
147 oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
148 sprintf(buffer, "%5.3f in", value * iscale * oscale / 72.0);
149 break;
150 case FRAC_INCH:
151 oscale = xobjs.pagelist[areawin->page]->outscale * INCHSCALE;
152 fraccalc(((value * iscale * oscale) / 72.0), buffer);
153 strcat(buffer, " in");
154 break;
158 /*----------------------------------------------------------------*/
159 /* set the global default line width. The unit used internally */
160 /* is twice the value passed through pointer "dataptr". */
161 /*----------------------------------------------------------------*/
163 void setwidth(xcWidget w, float *dataptr)
165 float oldvalue = *dataptr;
166 if (sscanf(_STR2, "%f", dataptr) == 0) {
167 *dataptr = oldvalue;
168 Wprintf("Illegal value");
169 return;
171 (*dataptr) *= 2.0;
172 if (oldvalue != *dataptr) drawarea(NULL, NULL, NULL);
175 /*--------------------------------------------------------------*/
176 /* Set text scale. */
177 /*--------------------------------------------------------------*/
179 void changetextscale(float newscale)
181 short *osel;
182 labelptr settext;
183 stringpart *strptr, *nextptr;
185 /* In edit mode, add font scale change. */
187 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
188 settext = *((labelptr *)EDITPART);
189 if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string, True,
190 areawin->topinstance)) {
191 undrawtext(settext);
192 strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
193 areawin->topinstance);
194 nextptr = findstringpart(areawin->textpos, NULL, settext->string,
195 areawin->topinstance);
196 if (strptr->type == FONT_SCALE)
197 strptr->data.scale = newscale;
198 else if (nextptr && nextptr->type == FONT_SCALE)
199 nextptr->data.scale = newscale;
200 else
201 labeltext(FONT_SCALE, (char *)&newscale);
202 redrawtext(settext);
204 else if (stringlength(settext->string, True, areawin->topinstance) > 0)
205 labeltext(FONT_SCALE, (char *)&newscale);
206 else (settext->scale = newscale);
209 /* Change scale on all selected text objects */
211 else if (areawin->selects > 0) {
212 float oldscale;
213 Boolean waschanged = FALSE;
214 for (osel = areawin->selectlist; osel < areawin->selectlist +
215 areawin->selects; osel++) {
216 if (SELECTTYPE(osel) == LABEL) {
217 settext = SELTOLABEL(osel);
218 oldscale = settext->scale;
219 if (oldscale != newscale) {
220 undrawtext(settext);
221 settext->scale = newscale;
222 redrawtext(settext);
223 register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
224 (genericptr)settext, (double)oldscale);
225 waschanged = TRUE;
229 if (waschanged) undo_finish_series();
233 /*--------------------------------------------------------------*/
234 /* Auto-scale the drawing to fit the declared page size. */
235 /* */
236 /* If the page is declared encapsulated, then do nothing. */
237 /* If a frame box is on the page, then scale to fit the frame */
238 /* to the declared page size, not the whole object. */
239 /*--------------------------------------------------------------*/
241 void autoscale(int page)
243 float newxscale, newyscale;
244 float scalefudge = (xobjs.pagelist[page]->coordstyle
245 == CM) ? CMSCALE : INCHSCALE;
246 int width, height;
247 polyptr framebox;
249 /* Check if auto-fit flag is selected */
250 if (!(xobjs.pagelist[page]->pmode & 2)) return;
251 /* Ignore auto-fit flag in EPS mode */
252 if (!(xobjs.pagelist[page]->pmode & 1)) return;
254 else if (topobject->bbox.width == 0 || topobject->bbox.height == 0) {
255 // Wprintf("Cannot auto-fit empty page");
256 return;
259 newxscale = (xobjs.pagelist[page]->pagesize.x -
260 (2 * xobjs.pagelist[page]->margins.x)) / scalefudge;
261 newyscale = (xobjs.pagelist[page]->pagesize.y -
262 (2 * xobjs.pagelist[page]->margins.y)) / scalefudge;
264 if ((framebox = checkforbbox(topobject)) != NULL) {
265 int i, minx, miny, maxx, maxy;
267 minx = maxx = framebox->points[0].x;
268 miny = maxy = framebox->points[0].y;
269 for (i = 1; i < framebox->number; i++) {
270 if (framebox->points[i].x < minx) minx = framebox->points[i].x;
271 else if (framebox->points[i].x > maxx) maxx = framebox->points[i].x;
272 if (framebox->points[i].y < miny) miny = framebox->points[i].y;
273 else if (framebox->points[i].y > maxy) maxy = framebox->points[i].y;
275 width = (maxx - minx);
276 height = (maxy - miny);
278 else {
280 width = toplevelwidth(areawin->topinstance, NULL);
281 height = toplevelheight(areawin->topinstance, NULL);
284 if (xobjs.pagelist[page]->orient == 0) { /* Portrait */
285 newxscale /= width;
286 newyscale /= height;
288 else {
289 newxscale /= height;
290 newyscale /= width;
292 xobjs.pagelist[page]->outscale = min(newxscale, newyscale);
295 /*--------------------------------------------------------------*/
296 /* Parse a string for possible units of measure. Convert to */
297 /* current units of measure, if necessary. Return the value */
298 /* in current units, as a type float. */
299 /*--------------------------------------------------------------*/
301 float parseunits(char *strptr)
303 short curtype;
304 Boolean inchunits = True;
305 float pv;
306 char units[12];
308 curtype = xobjs.pagelist[areawin->page]->coordstyle;
310 if (sscanf(strptr, "%f %11s", &pv, units) < 2)
311 return pv;
312 else {
313 if (!strncmp(units, "cm", 2) || !strncmp(units, "centimeters", 11))
314 inchunits = False;
315 switch(curtype) {
316 case CM:
317 return ((inchunits) ? (pv * 2.54) : pv);
318 default:
319 return ((inchunits) ? pv : (pv / 2.54));
324 /*--------------------------------------------------------------*/
325 /* Set the output page size, in the current unit of measure */
326 /* Return value: TRUE if _STR2 values were in inches, FALSE */
327 /* if in centimeters. */
328 /* XXX This API gives no good way to signal errors. */
329 /*--------------------------------------------------------------*/
331 Boolean setoutputpagesize(XPoint *dataptr)
333 float px, py;
334 char units[10], *expos;
335 #ifndef TCL_WRAPPER
336 Arg wargs[1];
337 #endif
339 strcpy(units, "in");
341 if (sscanf(_STR2, "%f %*c %f %9s", &px, &py, units) < 4) {
342 if (sscanf(_STR2, "%f %*c %f", &px, &py) < 3) {
343 if ((expos = strchr(_STR2, 'x')) == NULL) {
344 Wprintf("Illegal Form for page size.");
345 return FALSE;
347 else {
348 *expos = '\0';
349 if (sscanf(_STR2, "%f", &px) == 0 ||
350 sscanf(expos + 1, "%f %9s", &py, units) == 0) {
351 Wprintf("Illegal Form for page size.");
352 return FALSE;
358 /* Don't reduce page to less than the margins (1") or negative */
359 /* scales result. */
361 if ((px <= 2.0) || (py <= 2.0)) {
362 Wprintf("Page size too small for margins.");
363 return FALSE;
366 dataptr->x = (short)(px * 72.0);
367 dataptr->y = (short)(py * 72.0);
369 if (!strcmp(units, "cm")) {
370 dataptr->x /= 2.54;
371 dataptr->y /= 2.54;
372 return FALSE;
374 return TRUE;
377 /*--------------------------------------------------------------*/
378 /* Get the text size (global or selected, depending on mode */
379 /*--------------------------------------------------------------*/
381 labelptr gettextsize(float **floatptr)
383 labelptr settext = NULL;
384 short *osel;
385 stringpart *strptr, *nextptr;
386 const float f_one = 1.00;
388 if (floatptr) *floatptr = &areawin->textscale;
390 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
391 if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
392 True, areawin->topinstance)) {
393 settext = *((labelptr *)EDITPART);
394 strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
395 areawin->topinstance);
396 nextptr = findstringpart(areawin->textpos, NULL, settext->string,
397 areawin->topinstance);
398 if (strptr->type == FONT_SCALE) {
399 if (floatptr) *floatptr = &strptr->data.scale;
401 else if (nextptr && nextptr->type == FONT_SCALE) {
402 if (floatptr) *floatptr = &nextptr->data.scale;
404 else if (floatptr) *floatptr = (float *)(&f_one);
406 else {
407 settext = *((labelptr *)EDITPART);
408 if (floatptr) *floatptr = &(settext->scale);
411 else if (areawin->selects > 0) {
412 for (osel = areawin->selectlist; osel < areawin->selectlist +
413 areawin->selects; osel++) {
414 if (SELECTTYPE(osel) == LABEL) {
415 settext = SELTOLABEL(osel);
416 if (floatptr) *floatptr = &(settext->scale);
417 break;
421 return settext;
424 /*--------------------------------------------------------------*/
425 /* Set a character kern value */
426 /*--------------------------------------------------------------*/
428 void setkern(xcWidget w, stringpart *kpart)
430 char *sptr;
431 short kd[2];
433 kd[0] = kd[1] = 0;
435 if ((sptr = strchr(_STR2, ',')) == NULL)
436 Wprintf("Use notation X,Y");
437 else {
438 *sptr = '\0';
439 sscanf(_STR2, "%hd", &kd[0]);
440 sscanf(sptr + 1, "%hd", &kd[1]);
441 if (kpart == NULL)
442 labeltext(KERN, (char *)kd);
443 else {
444 labelptr curlabel = TOLABEL(EDITPART);
445 undrawtext(curlabel);
446 kpart->data.kern[0] = kd[0];
447 kpart->data.kern[1] = kd[1];
448 redrawtext(curlabel);
453 /*----------------------------------------------------------------*/
454 /* Set the drawing scale (specified as ratio X:Y) */
455 /*----------------------------------------------------------------*/
457 void setdscale(xcWidget w, XPoint *dataptr)
459 char *sptr;
461 if ((sptr = strchr(_STR2, ':')) == NULL)
462 Wprintf("Use ratio X:Y");
463 else {
464 *sptr = '\0';
465 sscanf(_STR2, "%hd", &(dataptr->x));
466 sscanf(sptr + 1, "%hd", &(dataptr->y));
467 Wprintf("New scale is %hd:%hd", dataptr->x, dataptr->y);
468 W1printf(" ");
472 /*----------------------------------------------------------------*/
473 /* Set the scale of an object or group of selected objects */
474 /*----------------------------------------------------------------*/
476 void setosize(xcWidget w, objinstptr dataptr)
478 float tmpres, oldsize;
479 Boolean waschanged = FALSE;
480 short *osel;
481 objinstptr nsobj;
482 int res = sscanf(_STR2, "%f", &tmpres);
484 // Negative values are flips---deal with them independently
486 if (tmpres < 0)
487 tmpres = -tmpres;
489 if (res == 0 || tmpres == 0) {
490 Wprintf("Illegal value");
491 return;
493 for (osel = areawin->selectlist; osel < areawin->selectlist +
494 areawin->selects; osel++) {
495 if (SELECTTYPE(osel) == OBJINST) {
496 nsobj = SELTOOBJINST(osel);
497 oldsize = nsobj->scale;
498 nsobj->scale = (oldsize < 0) ? -tmpres : tmpres;
500 if (oldsize != tmpres) {
501 register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
502 SELTOGENERIC(osel), (double)oldsize);
503 waschanged = TRUE;
507 if (waschanged) undo_finish_series();
508 pwriteback(areawin->topinstance);
509 drawarea(NULL, NULL, NULL);
512 /*----------------------------------------------------------------*/
513 /* Set the linewidth of all selected arcs, polygons, splines, and */
514 /* paths. */
515 /*----------------------------------------------------------------*/
517 void setwwidth(xcWidget w, void *dataptr)
519 float tmpres, oldwidth;
520 short *osel;
521 arcptr nsarc;
522 polyptr nspoly;
523 splineptr nsspline;
524 pathptr nspath;
526 if (sscanf(_STR2, "%f", &tmpres) == 0) {
527 Wprintf("Illegal value");
528 return;
530 else if (areawin->selects == 0) {
531 areawin->linewidth = tmpres;
533 else {
534 for (osel = areawin->selectlist; osel < areawin->selectlist +
535 areawin->selects; osel++) {
536 if (SELECTTYPE(osel) == ARC) {
537 nsarc = SELTOARC(osel);
538 oldwidth = nsarc->width;
539 nsarc->width = tmpres;
541 else if (SELECTTYPE(osel) == POLYGON) {
542 nspoly = SELTOPOLY(osel);
543 oldwidth = nspoly->width;
544 nspoly->width = tmpres;
546 else if (SELECTTYPE(osel) == SPLINE) {
547 nsspline = SELTOSPLINE(osel);
548 oldwidth = nsspline->width;
549 nsspline->width = tmpres;
551 else if (SELECTTYPE(osel) == PATH) {
552 nspath = SELTOPATH(osel);
553 oldwidth = nspath->width;
554 nspath->width = tmpres;
557 if (oldwidth != tmpres)
558 register_for_undo(XCF_Rescale, UNDO_MORE, areawin->topinstance,
559 SELTOGENERIC(osel), (double)oldwidth);
561 unselect_all();
562 pwriteback(areawin->topinstance);
563 drawarea(NULL, NULL, NULL);
567 /*--------------------------------------------------------------*/
568 /* Add a new font name to the list of known fonts */
569 /* Register the font number for the Alt-F cycling mechanism */
570 /* Tcl: depends on command tag mechanism for GUI menu update. */
571 /*--------------------------------------------------------------*/
573 #ifdef TCL_WRAPPER
575 void makenewfontbutton()
577 nfontnumbers++;
578 if (nfontnumbers == 1)
579 fontnumbers = (u_short *)malloc(sizeof(u_short));
580 else
581 fontnumbers = (u_short *)realloc(fontnumbers, nfontnumbers
582 * sizeof(u_short));
583 fontnumbers[nfontnumbers - 1] = fontcount - 1;
586 #endif /* TCL_WRAPPER */
588 /*---------------------------------------------------------------*/
589 /* Some Xcircuit routines using toggle and toggleexcl, */
590 /* put here because they reference the menu structures directly. */
591 /* */
592 /* Note that by bypassing addnewcolorentry(), the new colors in */
593 /* colorlist are NOT added to the GUI list of colors. */
594 /*---------------------------------------------------------------*/
596 void setcolorscheme(Boolean boolvalue)
598 int i;
600 if (boolvalue) {
601 colorlist[PARAMCOLOR].color.pixel = appdata.parampix;
602 colorlist[AUXCOLOR].color.pixel = appdata.auxpix;
603 colorlist[OFFBUTTONCOLOR].color.pixel = appdata.buttonpix;
604 colorlist[SELECTCOLOR].color.pixel = appdata.selectpix;
605 colorlist[GRIDCOLOR].color.pixel = appdata.gridpix;
606 colorlist[SNAPCOLOR].color.pixel = appdata.snappix;
607 colorlist[AXESCOLOR].color.pixel = appdata.axespix;
608 colorlist[BACKGROUND].color.pixel = appdata.bg;
609 colorlist[FOREGROUND].color.pixel = appdata.fg;
611 else {
612 colorlist[PARAMCOLOR].color.pixel = appdata.parampix2;
613 colorlist[AUXCOLOR].color.pixel = appdata.auxpix2;
614 colorlist[OFFBUTTONCOLOR].color.pixel = appdata.buttonpix2;
615 colorlist[SELECTCOLOR].color.pixel = appdata.selectpix2;
616 colorlist[GRIDCOLOR].color.pixel = appdata.gridpix2;
617 colorlist[SNAPCOLOR].color.pixel = appdata.snappix2;
618 colorlist[AXESCOLOR].color.pixel = appdata.axespix2;
619 colorlist[BACKGROUND].color.pixel = appdata.bg2;
620 colorlist[FOREGROUND].color.pixel = appdata.fg2;
623 colorlist[BARCOLOR].color.pixel = appdata.barpix;
624 colorlist[FILTERCOLOR].color.pixel = appdata.filterpix;
626 colorlist[LOCALPINCOLOR].color.pixel = appdata.localcolor;
627 colorlist[GLOBALPINCOLOR].color.pixel = appdata.globalcolor;
628 colorlist[INFOLABELCOLOR].color.pixel = appdata.infocolor;
629 colorlist[RATSNESTCOLOR].color.pixel = appdata.ratsnestcolor;
630 colorlist[BBOXCOLOR].color.pixel = appdata.bboxpix;
631 colorlist[CLIPMASKCOLOR].color.pixel = appdata.clipcolor;
632 colorlist[FIXEDBBOXCOLOR].color.pixel = appdata.fixedbboxpix;
634 /* Fill in pixel information */
636 for (i = 0; i < NUMBER_OF_COLORS; i++) {
637 unsigned short r, g, b;
639 /* Get the color the hard way by querying the X server colormap */
640 xc_get_color_rgb(colorlist[i].color.pixel, &r, &g, &b);
642 /* Store this information locally so we don't have to do */
643 /* the lookup the hard way in the future. */
645 colorlist[i].color.red = r;
646 colorlist[i].color.green = g;
647 colorlist[i].color.blue = b;
649 areawin->redraw_needed = True;
650 drawarea(NULL, NULL, NULL);
653 /*----------------------------------------------------------------*/
654 /* Change menu selection for reported measurement units */
655 /*----------------------------------------------------------------*/
657 #ifdef TCL_WRAPPER
659 void togglegrid(u_short type)
661 static char *stylenames[] = {
662 "decimal inches",
663 "fractional inches",
664 "centimeters",
665 "internal units", NULL
668 XcInternalTagCall(xcinterp, 3, "config", "coordstyle", stylenames[type]);
671 #endif /* TCL_WRAPPER */
673 /*----------------------------------------------------------------*/
674 /* Called by setgridtype() to complete setting the reported */
675 /* measurement units */
676 /*----------------------------------------------------------------*/
678 void getgridtype(xcWidget button, pointertype value, caddr_t calldata)
680 short oldtype = xobjs.pagelist[areawin->page]->coordstyle;
681 float scalefac = getpsscale(1.0, areawin->page) / INCHSCALE;
683 #ifndef TCL_WRAPPER
684 togglegridstyles(button);
685 #endif
686 xobjs.pagelist[areawin->page]->coordstyle = (short)value;
688 switch(value) {
689 case FRAC_INCH: case DEC_INCH: case INTERNAL:
690 if (oldtype == CM) {
691 xobjs.pagelist[areawin->page]->outscale *= scalefac;
692 #ifndef TCL_WRAPPER
693 /* Note: Tcl defines a method for selecting standard */
694 /* page sizes. We really DON'T want to reset the size */
695 /* just because we switched measurement formats! */
697 xobjs.pagelist[areawin->page]->pagesize.x = 612;
698 xobjs.pagelist[areawin->page]->pagesize.y = 792; /* letter */
699 #endif
701 break;
702 case CM:
703 if (oldtype != CM) {
704 xobjs.pagelist[areawin->page]->outscale *= scalefac;
705 #ifndef TCL_WRAPPER
706 xobjs.pagelist[areawin->page]->pagesize.x = 595;
707 xobjs.pagelist[areawin->page]->pagesize.y = 842; /* A4 */
708 #endif
710 break;
712 if (oldtype != xobjs.pagelist[areawin->page]->coordstyle) {
713 drawarea(NULL, NULL, NULL);
714 W1printf(" ");
718 /*------------------------------------------------------*/
719 /* Make new library, add new button to the "Libraries" */
720 /* cascaded menu, compose the library page, update the */
721 /* library directory, and go to that library page. */
722 /*------------------------------------------------------*/
724 void newlibrary(xcWidget w, caddr_t clientdata, caddr_t calldata)
726 int libnum = createlibrary(FALSE);
727 startcatalog(w, libnum, NULL);
730 /*----------------------------------------------*/
731 /* Find an empty library, and return its page */
732 /* number if it exists. Otherwise, return -1. */
733 /* This search does not include the so-called */
734 /* "User Library" (last library in list). */
735 /*----------------------------------------------*/
737 int findemptylib()
739 int i;
741 for (i = 0; i < xobjs.numlibs - 1; i++) {
742 if (xobjs.userlibs[i].number == 0)
743 return i;
745 return -1;
748 /*----------------------------------------------*/
749 /* Make new page; goto that page */
750 /* (wrapper for routine events.c:newpage()) */
751 /*----------------------------------------------*/
753 void newpagemenu(xcWidget w, pointertype value, caddr_t nulldata)
755 newpage((short)value);
758 #ifdef TCL_WRAPPER
760 /*----------------------------------------------*/
761 /* Make new library and add a new button to the */
762 /* "Libraries" cascaded menu. */
763 /*----------------------------------------------*/
765 int createlibrary(Boolean force)
767 /* xcWidget libmenu, newbutton, oldbutton; (jdk) */
768 #ifndef TCL_WRAPPER
769 Arg wargs[2];
770 #endif
771 /* char libstring[20]; (jdk) */
772 int libnum;
773 objectptr newlibobj;
775 /* If there's an empty library, return its number */
776 if ((!force) && (libnum = findemptylib()) >= 0) return (libnum + LIBRARY);
777 libnum = (xobjs.numlibs++) + LIBRARY;
778 xobjs.libtop = (objinstptr *)realloc(xobjs.libtop,
779 (libnum + 1) * sizeof(objinstptr));
780 xobjs.libtop[libnum] = xobjs.libtop[libnum - 1];
781 libnum--;
783 newlibobj = (objectptr) malloc(sizeof(object));
784 initmem(newlibobj);
785 xobjs.libtop[libnum] = newpageinst(newlibobj);
787 sprintf(newlibobj->name, "Library %d", libnum - LIBRARY + 1);
789 /* Create the library */
791 xobjs.userlibs = (Library *) realloc(xobjs.userlibs, xobjs.numlibs
792 * sizeof(Library));
793 xobjs.userlibs[libnum + 1 - LIBRARY] = xobjs.userlibs[libnum - LIBRARY];
794 xobjs.userlibs[libnum - LIBRARY].library = (objectptr *) malloc(sizeof(objectptr));
795 xobjs.userlibs[libnum - LIBRARY].number = 0;
796 xobjs.userlibs[libnum - LIBRARY].instlist = NULL;
798 sprintf(_STR2, "xcircuit::newlibrarybutton \"%s\"", newlibobj->name);
799 Tcl_Eval(xcinterp, _STR2);
801 /* Update the library directory to include the new page */
803 composelib(LIBLIB);
805 return libnum;
808 /*--------------------------------------------------------------*/
809 /* Routine called by newpage() if new button needs to be made */
810 /* to add to the "Pages" cascaded menu. */
811 /*--------------------------------------------------------------*/
813 void makepagebutton()
815 /* xcWidget pagemenu, newbutton; (jdk) */
816 /* char pagestring[10]; (jdk) */
818 /* make new entry in the menu */
820 sprintf(_STR2, "newpagebutton \"Page %d\"", xobjs.pages);
821 Tcl_Eval(xcinterp, _STR2);
823 /* Update the page directory */
825 composelib(PAGELIB);
828 /*----------------------------------------------------------------*/
829 /* Find the Page menu button associated with the page number */
830 /* (passed parameter) and set the label of that button to the */
831 /* object name (= page label) */
832 /*----------------------------------------------------------------*/
834 void renamepage(short pagenumber)
836 objinstptr thisinst = xobjs.pagelist[pagenumber]->pageinst;
837 char *pname, *plabel;
839 if ((pagenumber >= 0) && (pagenumber < xobjs.pages - 1) &&
840 (thisinst != NULL)) {
841 plabel = thisinst->thisobject->name;
842 pname = (char *)malloc(36 + strlen(plabel));
843 sprintf(pname, "catch {xcircuit::renamepage %d {%s}}", pagenumber + 1, plabel);
844 Tcl_Eval(xcinterp, pname);
845 free(pname);
849 /*--------------------------------------------------------------*/
850 /* Same routine as above, for Library page menu buttons */
851 /*--------------------------------------------------------------*/
853 void renamelib(short libnumber)
855 if (libnumber <= xobjs.numlibs) return;
857 sprintf(_STR2, "xcircuit::renamelib %d \"%s\"", libnumber - LIBRARY + 1,
858 xobjs.libtop[libnumber]->thisobject->name);
859 Tcl_Eval(xcinterp, _STR2);
862 /*--------------------------------------------------------------*/
863 /* Set the menu checkmarks on the color menu */
864 /*--------------------------------------------------------------*/
866 void setcolormark(int colorval)
868 /* Set GUI variables and execute any command tags associated */
869 /* with the "color" command */
871 #ifdef TCL_WRAPPER
872 char cstr[6];
874 if (colorval != DEFAULTCOLOR)
875 sprintf(cstr, "%5d", colorval);
877 XcInternalTagCall(xcinterp, 3, "color", "set", (colorval == DEFAULTCOLOR) ?
878 "inherit" : cstr);
879 #endif
882 /*----------------------------------------------------------------*/
883 /* Set the checkmarks on the element styles menu */
884 /*----------------------------------------------------------------*/
886 void setallstylemarks(u_short styleval)
888 /* Execute any command tags associated */
889 /* with the "fill" and "border" commands. */
891 char fstr[10];
892 int fillfactor;
893 const char *bptr;
895 const char *borders[] = {"solid", "unbordered", "dashed", "dotted", NULL};
896 enum BorderIdx { SolidIdx, UnborderedIdx, DashedIdx, DottedIdx };
898 if (styleval & FILLED) {
899 fillfactor = (int)(12.5 * (float)(1 + ((styleval & FILLSOLID) >> 5)));
900 if (fillfactor < 100)
901 sprintf(fstr, "%d", fillfactor);
902 else
903 strcpy(fstr, "solid");
905 else
906 strcpy(fstr, "unfilled");
908 switch (styleval & BORDERS) {
909 case DASHED:
910 bptr = borders[DashedIdx];
911 break;
912 case DOTTED:
913 bptr = borders[DottedIdx];
914 break;
915 case NOBORDER:
916 bptr = borders[UnborderedIdx];
917 break;
918 default:
919 bptr = borders[SolidIdx];
920 break;
923 XcInternalTagCall(xcinterp, 3, "fill", fstr,
924 (styleval & OPAQUE) ? "opaque" : "transparent");
925 XcInternalTagCall(xcinterp, 3, "border", "bbox", (styleval & BBOX) ? "true" :
926 "false");
927 XcInternalTagCall(xcinterp, 3, "border", "clipmask", (styleval & CLIPMASK) ?
928 "true" : "false");
929 XcInternalTagCall(xcinterp, 2, "border", (styleval & UNCLOSED) ? "unclosed" :
930 "closed");
931 XcInternalTagCall(xcinterp, 2, "border", bptr);
934 #endif /* TCL_WRAPPER */
936 /*--------------------------------------------------------------*/
937 /* Check for a bounding box polygon */
938 /*--------------------------------------------------------------*/
940 polyptr checkforbbox(objectptr localdata)
942 polyptr *cbbox;
944 for (cbbox = (polyptr *)localdata->plist; cbbox <
945 (polyptr *)localdata->plist + localdata->parts; cbbox++)
946 if (IS_POLYGON(*cbbox))
947 if ((*cbbox)->style & BBOX) return *cbbox;
949 return NULL;
952 /*--------------------------------------------------------------*/
953 /* Set a value for element style. "Mask" determines the bits */
954 /* to be affected, so that "value" may turn bits either on or */
955 /* off. */
956 /*--------------------------------------------------------------*/
958 int setelementstyle(xcWidget w, u_short value, u_short mask)
960 Boolean preselected, selected = False;
961 short *sstyle;
962 u_short newstyle, oldstyle;
964 if (areawin->selects == 0) {
965 preselected = FALSE;
966 if (value & BBOX)
967 checkselect(POLYGON);
968 else
969 checkselect(ARC | SPLINE | POLYGON | PATH);
971 else preselected = TRUE;
973 if (areawin->selects > 0) {
974 if (value & BBOX) {
975 polyptr ckp;
976 if (areawin->selects != 1) {
977 Wprintf("Choose only one polygon to be the bounding box");
978 return -1;
980 else if (SELECTTYPE(areawin->selectlist) != POLYGON) {
981 Wprintf("Bounding box can only be a polygon");
982 return -1;
984 else if (((ckp = checkforbbox(topobject)) != NULL) &&
985 (ckp != SELTOPOLY(areawin->selectlist))) {
986 Wprintf("Only one bounding box allowed per page");
987 return -1;
991 for (sstyle = areawin->selectlist; sstyle < areawin->selectlist
992 + areawin->selects; sstyle++) {
993 short stype = SELECTTYPE(sstyle);
994 if (stype & (ARC | POLYGON | SPLINE | PATH)) {
995 short *estyle;
996 switch (stype) {
997 case ARC:
998 estyle = &((SELTOARC(sstyle))->style);
999 break;
1000 case SPLINE:
1001 estyle = &((SELTOSPLINE(sstyle))->style);
1002 break;
1003 case POLYGON:
1004 estyle = &((SELTOPOLY(sstyle))->style);
1005 break;
1006 case PATH:
1007 estyle = &((SELTOPATH(sstyle))->style);
1008 break;
1010 oldstyle = newstyle = *estyle;
1011 newstyle &= ~(mask);
1012 newstyle |= value;
1014 if (oldstyle != newstyle) {
1015 if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
1016 Wprintf("Must have either a border or filler");
1017 continue;
1020 SetForeground(dpy, areawin->gc, BACKGROUND);
1021 easydraw(*sstyle, DOFORALL);
1023 *estyle = newstyle;
1024 if (mask & BBOX)
1025 (SELTOPOLY(sstyle))->color = (value & BBOX) ? BBOXCOLOR
1026 : DEFAULTCOLOR;
1028 SetForeground(dpy, areawin->gc, SELECTCOLOR);
1029 easydraw(*sstyle, DOFORALL);
1031 #ifdef TCL_WRAPPER
1032 register_for_undo(XCF_ChangeStyle,
1033 (sstyle == areawin->selectlist + areawin->selects - 1) ?
1034 UNDO_DONE : UNDO_MORE, areawin->topinstance,
1035 SELTOGENERIC(sstyle), (int)oldstyle);
1036 #else
1037 /* Tcl version differs in that the element is not deselected after */
1039 register_for_undo(XCF_ChangeStyle, UNDO_MORE, areawin->topinstance,
1040 SELTOGENERIC(sstyle), (int)oldstyle);
1041 #endif
1043 selected = True;
1047 if (selected)
1048 pwriteback(areawin->topinstance);
1049 else {
1050 newstyle = areawin->style;
1051 if (value & BBOX) {
1052 Wprintf("Cannot set default style to Bounding Box");
1053 newstyle &= ~(BBOX);
1054 return -1;
1056 else if (value & CLIPMASK) {
1057 Wprintf("Cannot set default style to Clip Mask");
1058 newstyle &= ~(CLIPMASK);
1059 return -1;
1061 else {
1062 newstyle &= ~mask;
1063 newstyle |= value;
1066 if ((newstyle & NOBORDER) && !(newstyle & FILLED)) {
1067 Wprintf("Must have either a border or filler");
1068 return -1;
1070 areawin->style = newstyle;
1071 #ifndef TCL_WRAPPER
1072 overdrawpixmap(w);
1073 #endif
1075 #ifndef TCL_WRAPPER
1076 setallstylemarks(newstyle);
1077 #endif
1078 if (!preselected)
1079 unselect_all();
1081 return (int)newstyle;
1084 /*-----------------------------------------------*/
1085 /* Set the color value for all selected elements */
1086 /*-----------------------------------------------*/
1088 #ifdef TCL_WRAPPER
1090 void setcolor(xcWidget w, int cindex)
1092 short *scolor;
1093 int *ecolor, oldcolor;
1094 Boolean selected = False;
1095 stringpart *strptr, *nextptr;
1097 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1098 labelptr curlabel = TOLABEL(EDITPART);
1099 strptr = findstringpart(areawin->textpos - 1, NULL, curlabel->string,
1100 areawin->topinstance);
1101 nextptr = findstringpart(areawin->textpos, NULL, curlabel->string,
1102 areawin->topinstance);
1103 if (strptr && strptr->type == FONT_COLOR) {
1104 undrawtext(curlabel);
1105 strptr->data.color = cindex;
1106 redrawtext(curlabel);
1108 else if (nextptr && nextptr->type == FONT_COLOR) {
1109 undrawtext(curlabel);
1110 nextptr->data.color = cindex;
1111 redrawtext(curlabel);
1113 else {
1114 sprintf(_STR2, "%d", cindex);
1115 labeltext(FONT_COLOR, (char *)&cindex);
1119 else if (areawin->selects > 0) {
1120 for (scolor = areawin->selectlist; scolor < areawin->selectlist
1121 + areawin->selects; scolor++) {
1122 ecolor = &(SELTOCOLOR(scolor));
1123 oldcolor = *ecolor;
1124 *ecolor = cindex;
1125 selected = True;
1127 register_for_undo(XCF_Color, (scolor == areawin->selectlist
1128 + areawin->selects - 1) ? UNDO_DONE : UNDO_MORE,
1129 areawin->topinstance,
1130 SELTOGENERIC(scolor), (int)oldcolor);
1134 setcolormark(cindex);
1135 if (!selected) {
1136 if (eventmode != TEXT_MODE && eventmode != ETEXT_MODE)
1137 areawin->color = cindex;
1139 else pwriteback(areawin->topinstance);
1142 /*--------------------------------------------------------------*/
1143 /* Set the menu checkmarks on the font menu */
1144 /*--------------------------------------------------------------*/
1146 void togglefontmark(int fontval)
1148 if (fonts[fontval].family != NULL)
1149 XcInternalTagCall(xcinterp, 3, "label", "family", fonts[fontval].family);
1152 /*------------------------------------------------------*/
1153 /* Set checkmarks on label style menu */
1154 /* fvalue is for font, jvalue is for anchoring */
1155 /*------------------------------------------------------*/
1157 void togglestylemark(int styleval)
1159 char *cstyle = translatestyle(styleval);
1160 if (cstyle != NULL)
1161 XcInternalTagCall(xcinterp, 3, "label", "style", cstyle);
1164 /*------------------------------------------------------*/
1165 /* Set checkmarks on label encoding menu */
1166 /*------------------------------------------------------*/
1168 void toggleencodingmark(int encodingval)
1170 char *cenc = translateencoding(encodingval);
1171 if (cenc != NULL)
1172 XcInternalTagCall(xcinterp, 3, "label", "encoding", cenc);
1175 /*------------------------------------------------------*/
1176 /* Set checkmarks on label anchoring & flags menu */
1177 /*------------------------------------------------------*/
1179 void toggleanchormarks(int anchorvalue)
1181 XcInternalTagCall(xcinterp, 4, "label", "anchor", (anchorvalue & RIGHT) ? "right" :
1182 (anchorvalue & NOTLEFT) ? "center" : "left",
1183 (anchorvalue & TOP) ? "top" : (anchorvalue & NOTBOTTOM) ? "middle" : "bottom");
1184 XcInternalTagCall(xcinterp, 3, "label", "justify", (anchorvalue & JUSTIFYRIGHT) ?
1185 "right" : (anchorvalue & TEXTCENTERED) ? "center" : (anchorvalue & JUSTIFYBOTH)
1186 ? "both" : "left");
1187 XcInternalTagCall(xcinterp, 3, "label", "flipinvariant", (anchorvalue & FLIPINV) ?
1188 "true" : "false");
1189 XcInternalTagCall(xcinterp, 3, "label", "latex", (anchorvalue & LATEXLABEL) ?
1190 "true" : "false");
1191 XcInternalTagCall(xcinterp, 3, "label", "visible", (anchorvalue & PINVISIBLE) ?
1192 "true" : "false");
1195 /*-------------------------------------------------------------*/
1196 /* Simultaneously set all relevant checkmarks for a text label */
1197 /*-------------------------------------------------------------*/
1199 void setfontmarks(short fvalue, short jvalue)
1201 if ((fvalue >= 0) && (fvalue < fontcount)) {
1202 toggleencodingmark(fvalue);
1203 togglestylemark(fvalue);
1204 togglefontmark(fvalue);
1206 toggleanchormarks(jvalue);
1209 #endif /* TCL_WRAPPER */
1211 /*--------------------------------------------------------------*/
1212 /* Parameterize a label string (wrapper for parameterize()). */
1213 /* Assumes that the name has been generated by the popup prompt */
1214 /* and is therefore held in variable _STR2 */
1215 /*--------------------------------------------------------------*/
1217 void stringparam(xcWidget w, caddr_t clientdata, caddr_t calldata)
1219 genericptr *settext;
1221 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1222 settext = (genericptr *)EDITPART;
1223 makeparam(TOLABEL(settext), _STR2);
1224 if (eventmode == ETEXT_MODE)
1225 unselect_all();
1226 else
1227 /* Move cursor position to account for the parameter */
1228 /* start and end markers that have been added to the */
1229 /* string. */
1230 areawin->textpos += 2;
1231 setparammarks(NULL);
1233 else if (checkselect(LABEL)) parameterize(P_SUBSTRING, _STR2, -1);
1236 /*--------------------------------------------------------------*/
1237 /* Numerical parameterization (wrapper for parameterize()). */
1238 /*--------------------------------------------------------------*/
1240 void startparam(xcWidget w, pointertype value, caddr_t calldata)
1242 if (value == (pointertype)P_SUBSTRING) {
1243 strcpy(_STR2, (calldata != NULL) ? (char *)calldata : "substring");
1244 stringparam(w, NULL, NULL);
1246 else if ((eventmode != NORMAL_MODE) || (areawin->selects > 0))
1247 parameterize((int)value, (char *)calldata, -1);
1250 /*---------------------------------------------------------------*/
1251 /* Unparameterize a label string (wrapper for unparameterize()). */
1252 /*---------------------------------------------------------------*/
1254 void startunparam(xcWidget w, pointertype value, caddr_t calldata)
1256 if (areawin->selects > 0)
1257 unparameterize((int)value);
1258 unselect_all();
1259 setparammarks(NULL);
1262 /*----------------------------------------------------------------*/
1263 /* Set checkmarks on font menu according to the global defaults */
1264 /*----------------------------------------------------------------*/
1266 void setdefaultfontmarks()
1268 setfontmarks(areawin->psfont, areawin->anchor);
1271 /*----------------------------------------------------------------*/
1272 /* Pick up font name from _STR2 and pass it to loadfontfile() */
1273 /*----------------------------------------------------------------*/
1275 void locloadfont(xcWidget w, char *value)
1277 loadfontfile(_STR2);
1278 free(value);
1281 /*----------------------------------------------------------------*/
1282 /* Find the best matching font given new font, style, or encoding */
1283 /*----------------------------------------------------------------*/
1284 /* newfont, style, or encoding = -1 when not applicable */
1285 /* Return the number of the best matching font. */
1286 /*----------------------------------------------------------------*/
1288 short findbestfont(short curfont, short newfont, short style, short encoding) {
1290 char *newfamily;
1291 short i, newstyle, newenc;
1293 if (fontcount == 0) return -1;
1294 if (curfont < 0) curfont = 0;
1296 if (newfont < 0)
1297 newfamily = fonts[curfont].family;
1298 else if (newfont >= fontcount) { /* move to next font family */
1299 short newidx;
1300 newfont = 0;
1301 while (strcmp(fonts[fontnumbers[newfont]].family, fonts[curfont].family))
1302 newfont++;
1303 newidx = (newfont + 1) % nfontnumbers;
1304 while (!strcmp(fonts[curfont].family, fonts[fontnumbers[newidx]].family) &&
1305 newfont != newidx)
1306 newidx = (newidx + 1) % nfontnumbers;
1307 newfamily = fonts[fontnumbers[newidx]].family;
1308 newfont = fontnumbers[newidx];
1310 else
1311 newfamily = fonts[newfont].family;
1313 if (style < 0)
1314 newstyle = fonts[curfont].flags & 0x03;
1315 else
1316 newstyle = style & 0x03;
1318 if (encoding < 0)
1319 newenc = fonts[curfont].flags & 0xf80;
1320 else
1321 newenc = encoding << 7;
1323 /* Best position is a match on all conditions */
1325 for (i = 0; i < fontcount; i++)
1326 if ((!strcmp(fonts[i].family, newfamily)) &&
1327 ((fonts[i].flags & 0x03) == newstyle) &&
1328 ((fonts[i].flags & 0xf80) == newenc))
1329 return i;
1331 /* Fallback position 1: Match requested property and one other. */
1332 /* order of preference: */
1333 /* Requested property Priority 1 Priority 2 */
1334 /* Font Style Encoding */
1335 /* Style Font (none) */
1336 /* Encoding Font (none) */
1338 for (i = 0; i < fontcount; i++) {
1339 if (newfont >= 0) {
1340 if ((!strcmp(fonts[i].family, newfamily)) &&
1341 (fonts[i].flags & 0x03) == newstyle) return i;
1343 else if (style >= 0) {
1344 if (((fonts[i].flags & 0x03) == newstyle) &&
1345 (!strcmp(fonts[i].family, newfamily))) return i;
1347 else if (encoding >= 0) {
1348 if (((fonts[i].flags & 0xf80) == newenc) &&
1349 (!strcmp(fonts[i].family, newfamily))) return i;
1353 for (i = 0; i < fontcount; i++) {
1354 if (newfont >= 0) {
1355 if ((!strcmp(fonts[i].family, newfamily)) &&
1356 ((fonts[i].flags & 0xf80) >> 7) == newenc) return i;
1360 /* Fallback position 2: Match only the requested property. */
1361 /* For font selection only: Don't want to select a new font */
1362 /* just because a certain style or encoding wasn't available.*/
1364 for (i = 0; i < fontcount; i++) {
1365 if (newfont >= 0) {
1366 if (!strcmp(fonts[i].family, newfamily)) return i;
1370 /* Failure to find matching font property */
1372 if (style >= 0) {
1373 Wprintf("Font %s not available in this style", newfamily);
1375 else {
1376 Wprintf("Font %s not available in this encoding", newfamily);
1378 return (-1);
1381 /*----------------------------------------------------------------*/
1382 /* Set the font. This depends on the system state as to whether */
1383 /* font is set at current position in label, for an entire label, */
1384 /* or as the default font to begin new labels. */
1385 /*----------------------------------------------------------------*/
1387 void setfontval(xcWidget w, pointertype value, labelptr settext)
1389 int newfont;
1390 short i, tc;
1391 stringpart *strptr;
1393 if (settext != NULL) {
1395 /* if last byte was a font designator, use it */
1397 if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
1398 True, areawin->topinstance)) {
1399 strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
1400 areawin->topinstance);
1401 if (strptr->type == FONT_NAME) {
1402 tc = strptr->data.font;
1403 i = findbestfont(tc, (short)value, -1, -1);
1404 if (i >= 0) {
1405 undrawtext(settext);
1406 strptr->data.font = i;
1407 redrawtext(settext);
1408 if (w != NULL) {
1409 charreport(settext);
1410 togglefontmark(i);
1413 return;
1417 /* otherwise, look for the last style used in the string */
1418 tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
1420 else tc = areawin->psfont;
1422 /* Font change command will always find a value since at least one */
1423 /* font has to exist for the font menu button to exist. */
1425 if ((newfont = (int)findbestfont(tc, (short)value, -1, -1)) < 0) return;
1427 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1428 Wprintf("Font is now %s", fonts[newfont].psname);
1429 sprintf(_STR2, "%d", newfont);
1430 labeltext(FONT_NAME, (char *)&newfont);
1432 else {
1433 Wprintf("Default font is now %s", fonts[newfont].psname);
1434 areawin->psfont = newfont;
1437 if (w != NULL) togglefontmark(newfont);
1440 /*----------------------------------------------------------------*/
1441 /* Wrapper for routine setfontval() */
1442 /*----------------------------------------------------------------*/
1444 void setfont(xcWidget w, pointertype value, caddr_t calldata)
1446 short *fselect;
1447 labelptr settext;
1448 short labelcount = 0;
1449 Boolean preselected;
1451 if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
1452 eventmode == EFONTCAT_MODE) return;
1454 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1455 settext = *((labelptr *)EDITPART);
1456 setfontval(w, value, settext);
1457 charreport(settext);
1459 else {
1460 if (areawin->selects == 0) {
1461 checkselect(LABEL);
1462 preselected = FALSE;
1464 else preselected = TRUE;
1465 areawin->textpos = 1;
1466 for (fselect = areawin->selectlist; fselect < areawin->selectlist +
1467 areawin->selects; fselect++) {
1468 if (SELECTTYPE(fselect) == LABEL) {
1469 labelcount++;
1470 settext = SELTOLABEL(fselect);
1471 setfontval(NULL, value, settext);
1474 if (labelcount == 0) setfontval(w, value, NULL);
1475 else if (!preselected) unselect_all();
1479 /*----------------------------------------------------------------*/
1480 /* Set the style (bold, italic, normal) for the font, similarly */
1481 /* to the above routine setfontval(). */
1482 /*----------------------------------------------------------------*/
1484 void setfontstyle(xcWidget w, pointertype value, labelptr settext)
1486 int newfont;
1487 short i, tc;
1488 stringpart *strptr;
1490 if (settext != NULL) {
1492 /* if last byte was a font designator, use it */
1494 if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
1495 True, areawin->topinstance)) {
1496 strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
1497 areawin->topinstance);
1498 if (strptr->type == FONT_NAME) {
1499 tc = strptr->data.font;
1501 /* find font which matches family and style, if available */
1503 i = findbestfont(tc, -1, (short)value, -1);
1504 if (i >= 0) {
1505 undrawtext(settext);
1506 strptr->data.font = i;
1507 redrawtext(settext);
1508 if (w != NULL) {
1509 charreport(settext);
1510 #ifndef TCL_WRAPPER
1511 togglefontstyles(w);
1512 #endif
1515 return;
1519 /* Otherwise, look for the last font used in the string */
1520 /* Fix by Dimitri Princen. Was areawin->textpos - 2; was there a */
1521 /* reason for that? */
1523 tc = findcurfont(areawin->textpos, settext->string, areawin->topinstance);
1525 else tc = areawin->psfont;
1527 if ((newfont = (int)findbestfont(tc, -1, (short)value, -1)) < 0) return;
1529 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1530 Wprintf("Font is now %s", fonts[newfont].psname);
1531 sprintf(_STR2, "%d", newfont);
1532 labeltext(FONT_NAME, (char *)&newfont);
1534 else {
1535 Wprintf("Default font is now %s", fonts[newfont].psname);
1536 areawin->psfont = newfont;
1538 #ifdef TCL_WRAPPER
1539 toggleencodingmark(value);
1540 #else
1541 togglefontstyles(w);
1542 #endif
1545 /*----------------------------------------------------------------*/
1546 /* Wrapper for routine setfontstyle() */
1547 /*----------------------------------------------------------------*/
1549 void fontstyle(xcWidget w, pointertype value, caddr_t nulldata)
1551 short *fselect;
1552 labelptr settext;
1553 short labelcount = 0;
1554 Boolean preselected;
1556 if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
1557 eventmode == EFONTCAT_MODE) return;
1559 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1560 settext = *((labelptr *)EDITPART);
1561 setfontstyle(w, value, settext);
1562 charreport(settext);
1564 else {
1565 if (areawin->selects == 0) {
1566 checkselect(LABEL);
1567 preselected = FALSE;
1569 else preselected = TRUE;
1570 areawin->textpos = 1;
1571 for (fselect = areawin->selectlist; fselect < areawin->selectlist +
1572 areawin->selects; fselect++) {
1573 if (SELECTTYPE(fselect) == LABEL) {
1574 labelcount++;
1575 settext = SELTOLABEL(fselect);
1576 setfontstyle(NULL, value, settext);
1579 if (labelcount == 0) setfontstyle(w, value, NULL);
1580 else if (!preselected) unselect_all();
1584 /*----------------------------------------------------------------*/
1585 /* Set the encoding (standard, ISO-Latin1, special) for the font, */
1586 /* similarly to the above routine setfontval(). */
1587 /*----------------------------------------------------------------*/
1589 void setfontencoding(xcWidget w, pointertype value, labelptr settext)
1591 int newfont;
1592 short i, tc;
1593 stringpart *strptr;
1595 if (settext != NULL) {
1597 /* if last byte was a font designator, use it */
1599 if (areawin->textpos > 0 || areawin->textpos < stringlength(settext->string,
1600 True, areawin->topinstance)) {
1601 strptr = findstringpart(areawin->textpos - 1, NULL, settext->string,
1602 areawin->topinstance);
1603 if (strptr->type == FONT_NAME) {
1604 tc = strptr->data.font;
1606 i = findbestfont(tc, -1, -1, (short)value);
1607 if (i >= 0) {
1608 undrawtext(settext);
1609 strptr->data.font = i;
1610 redrawtext(settext);
1611 if (w != NULL) {
1612 charreport(settext);
1613 #ifdef TCL_WRAPPER
1614 toggleencodingmark(value);
1615 #else
1616 toggleencodings(w);
1617 #endif
1620 return;
1624 /* otherwise, look for the last style used in the string */
1625 tc = findcurfont(areawin->textpos - 2, settext->string, areawin->topinstance);
1627 else tc = areawin->psfont;
1629 if ((newfont = (int)findbestfont(tc, -1, -1, (short)value)) < 0) return;
1631 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1632 Wprintf("Font is now %s", fonts[newfont].psname);
1633 sprintf(_STR2, "%d", newfont);
1634 labeltext(FONT_NAME, (char *)&newfont);
1636 else {
1637 Wprintf("Default font is now %s", fonts[newfont].psname);
1638 areawin->psfont = newfont;
1641 #ifndef TCL_WRAPPER
1642 toggleencodings(w);
1643 #endif
1646 /*----------------------------------------------------------------*/
1647 /* Wrapper for routine setfontencoding() */
1648 /*----------------------------------------------------------------*/
1650 void fontencoding(xcWidget w, pointertype value, caddr_t nulldata)
1652 short *fselect;
1653 labelptr settext;
1654 short labelcount = 0;
1655 Boolean preselected;
1657 if (eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
1658 eventmode == EFONTCAT_MODE) return;
1660 if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
1661 settext = *((labelptr *)EDITPART);
1662 setfontencoding(w, value, settext);
1663 charreport(settext);
1665 else {
1666 if (areawin->selects == 0) {
1667 checkselect(LABEL);
1668 preselected = FALSE;
1670 else preselected = TRUE;
1671 areawin->textpos = 1;
1672 for (fselect = areawin->selectlist; fselect < areawin->selectlist +
1673 areawin->selects; fselect++) {
1674 if (SELECTTYPE(fselect) == LABEL) {
1675 labelcount++;
1676 settext = SELTOLABEL(fselect);
1677 setfontencoding(NULL, value, settext);
1680 if (labelcount == 0) setfontencoding(w, value, NULL);
1681 else if (!preselected) unselect_all();
1685 /*----------------------------------------------*/
1686 /* Generate the table of special characters */
1687 /* */
1688 /* Return FALSE if the edited label is LaTeX- */
1689 /* compatible, since LaTeX text does not */
1690 /* usually contain special characters, but it */
1691 /* does contain a lot of backslashes. */
1692 /*----------------------------------------------*/
1694 Boolean dospecial()
1696 labelptr curlabel;
1697 int cfont;
1699 curlabel = TOLABEL(EDITPART);
1700 if (curlabel->anchor & LATEXLABEL) return False;
1702 cfont = findcurfont(areawin->textpos, curlabel->string, areawin->topinstance);
1703 composefontlib(cfont);
1704 startcatalog(NULL, FONTLIB, NULL);
1705 return True;
1708 /*-------------------------------------------------------------------------*/