home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff280.lzh / Graph / object / label.c < prev    next >
C/C++ Source or Header  |  1989-11-20  |  20KB  |  669 lines

  1. /*
  2.  *                 GRAPH, Version 1.00 - 4 August 1989
  3.  *
  4.  *            Copyright 1989, David Gay. All Rights Reserved.
  5.  *            This software is freely redistrubatable.
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <intuition/intuition.h>
  10. #include <graphics/text.h>
  11. #include <string.h>
  12. #include <limits.h>
  13.  
  14. #include "object.h"
  15. #include "object/default.h"
  16. #include "file.h"
  17. #include "graph.h"
  18. #include "uio.h"
  19. #include "coords.h"
  20. #include "grph.h"
  21. #include "user/gadgets.h"
  22. #include "graphics.h"
  23. #include "tracker.h"
  24.  
  25. #include <proto/exec.h>
  26. #include <proto/intuition.h>
  27. #include <proto/graphics.h>
  28.  
  29. #define LABELLEN 256
  30. #define LABELHEIGHT 10
  31. #define LABELFONT "topaz.font"
  32. #define FONTLIST 2
  33.  
  34. /* The various justification possibilities */
  35. enum justify { top, centre, bottom };
  36.  
  37. /* (private) class label, inherits from object */
  38. struct label
  39. {
  40.     struct object o;
  41.     char text[LABELLEN]; /* What to display, \ for newlines */
  42.     BYTE colour;
  43.     char fname[FONTLEN]; /* font name */
  44.     int fheight;         /* font height */
  45.     double x, y;         /* text position */
  46.     double dx, dy;       /* offset from position, in inches */
  47.     enum justify jx, jy; /* justification (x & y axes) */
  48.  
  49.     char selected;
  50.     /* Temp, etc vars */
  51.     char broken[LABELLEN];   /* Text, separated into lines (separated by NULLs)
  52.  */
  53.     int nblines;             /* number of lines */
  54.     struct Rectangle extent; /* Size of rectangle taken by text */
  55.     int bw, bh;              /* Size of bitmap (for moving) */
  56.     struct Rectangle lims;   /* Rectangle taken up on screen */
  57.     int x0, y0;              /* x & y in screen coords (wthout ddx, ddy) */
  58.     struct TextFont *font, *newfont; /* the font (newfont for inform/confirm) *
  59. /
  60.     double oldx, oldy;       /* position before move */
  61.     int ddx, ddy;            /* dx, dy in pixels */
  62.     struct Region *ref;
  63.     struct RastPort bkgd;    /* Rastport & bitmap for moves */
  64.     struct BitMap bkgd_bm;
  65. };
  66.  
  67. /*-------------------------------------------------------------------------*/
  68. /*                       label class implementation                        */
  69. /*-------------------------------------------------------------------------*/
  70.  
  71. /* Allocates bitmap for saving background while moving */
  72. /* Assumes 2 bit planes */
  73. static int alloc_bkgd_label(struct label *this)
  74. {
  75.     BYTE *data;
  76.  
  77.     if (data = AllocMem(2 * RASSIZE(this->bw, this->bh), MEMF_CHIP))
  78.     {
  79.         InitBitMap(&this->bkgd_bm, 2, this->bw, this->bh);
  80.         this->bkgd_bm.Planes[0] = (PLANEPTR)data;
  81.         this->bkgd_bm.Planes[1] = (PLANEPTR)(data + RASSIZE(this->bw, this->bh)
  82. );
  83.         InitRastPort(&this->bkgd);
  84.         this->bkgd.BitMap = &this->bkgd_bm;
  85.     }
  86.     return data != 0;
  87. }
  88.  
  89. /* Frees bitmap alloced above */
  90. static void free_bkgd_label(struct label *this)
  91. {
  92.     FreeMem(this->bkgd_bm.Planes[0], 2 * RASSIZE(this->bw, this->bh));
  93. }
  94.  
  95. /* Save scrren background into temp space */
  96. static void save_bkgd_label(struct label *this)
  97. {
  98.     ClipBlit(this->o.g->io.rw->rp, this->lims.MinX, this->lims.MinY, &this->bkg
  99. d, 0, 0, this->bw, this->bh, 0xc0);
  100. }
  101.  
  102. /* Copies saved background back to the screen */
  103. static void restore_bkgd_label(struct label *this)
  104. {
  105.     ClipBlit(&this->bkgd, 0, 0, this->o.g->io.rw->rp, this->lims.MinX, this->li
  106. ms.MinY, this->bw, this->bh, 0xc0);
  107. }
  108.  
  109. /* Do all the precalculations */
  110. static void setup_label(struct label *this)
  111. {
  112.     struct TextFont *font = this->font;
  113.     char *srch, *nl;
  114.  
  115.     this->ddx = xinch2dots(this->o.g, this->dx);
  116.     this->ddy = yinch2dots(this->o.g, this->dy);
  117.  
  118.     /* Break up label & calculate rectangle used */
  119.     srch = strcpy(this->broken, this->text);
  120.     this->nblines = 0;
  121.     this->extent.MaxX = 0;
  122.     this->extent.MinX = INT_MAX;
  123.     do
  124.     {
  125.         struct TextExtent te;
  126.  
  127.         nl = strchr(srch, '\\');
  128.  
  129.         if (nl && *(nl + 1) == '\\') /* add single slash */
  130.             movmem(nl + 1, nl, LABELLEN - (nl - this->broken) - 1);
  131.         else
  132.         {
  133.             this->nblines++;
  134.             if (nl) *nl = '\0';
  135.             /* Check space for this line */
  136.             TextExtent(srch, font, &te);
  137.             if (te.te_Extent.MaxX > this->extent.MaxX) this->extent.MaxX = te.t
  138. e_Extent.MaxX;
  139.             if (te.te_Extent.MinX < this->extent.MinX) this->extent.MinX = te.t
  140. e_Extent.MinX;
  141.         }
  142.         srch = nl + 1;
  143.     } while (nl);
  144.  
  145.     this->extent.MinY = 0;
  146.     this->extent.MaxY = this->nblines * font->tf_YSize;
  147.     this->bw = this->extent.MaxX - this->extent.MinX + 1;
  148.     this->bh = this->extent.MaxY - this->extent.MinY + 1;
  149. }
  150.  
  151. /* Work out rectangle used by text */
  152. static void calc_rect(struct label *this)
  153. {
  154.     struct graph *g = this->o.g;
  155.     struct RWindow *rw = g->io.rw;
  156.     int delta, x0, y0;
  157.  
  158.     /* Find origin */
  159.     /* Default */
  160.     x0 = (this->x0 = ftol(rw->sx(rw, this->x))) + this->ddx;
  161.     y0 = (this->y0 = ftol(rw->sy(rw, this->y))) + this->ddy;
  162.  
  163.     /* Adjust for justification */
  164.     switch (this->jx)
  165.     {
  166.         case centre:
  167.             x0 -= this->bw / 2;
  168.             break;
  169.         case bottom: /* right */
  170.             x0 -= this->bw;
  171.             break;
  172.     }
  173.     switch (this->jy)
  174.     {
  175.         case centre:
  176.             y0 -= this->bh / 2;
  177.             break;
  178.         case bottom: /* right */
  179.             y0 -= this->bh;
  180.             break;
  181.     }
  182.     /* Extent defines actual rectangle */
  183.     this->lims.MinX = x0 + this->extent.MinX;
  184.     this->lims.MaxX = x0 + this->extent.MaxX;
  185.     this->lims.MinY = y0 + this->extent.MinY;
  186.     this->lims.MaxY = y0 + this->extent.MaxY;
  187.  
  188.     /* Make sure that it stays visible */
  189.     /* Could one reduce the number of flops ? */
  190.     /* Idea: Generalise inform/confirm */
  191.     if ((delta = ftol(rw->sx(rw, g->a.x.min)) - this->lims.MinX) > 0 ||
  192.         (delta = ftol(rw->sx(rw, g->a.x.max)) - this->lims.MaxX) < 0)
  193.     {
  194.         this->x0 += delta;
  195.         this->lims.MinX += delta;
  196.         this->lims.MaxX += delta;
  197.     }
  198.     if ((delta = ftol(rw->sy(rw, g->a.y.max)) - this->lims.MinY) > 0 ||
  199.         (delta = ftol(rw->sy(rw, g->a.y.min)) - this->lims.MaxY) < 0)
  200.     {
  201.         this->y0 += delta;
  202.         this->lims.MinY += delta;
  203.         this->lims.MaxY += delta;
  204.     }
  205. }
  206.  
  207. /* Add the current position to the region */
  208. static void add_region(struct label *this)
  209. {
  210.     if (!this->ref) this->ref = NewRegion();
  211.     if (this->ref && !OrRectRegion(this->ref, &this->lims))
  212.     {
  213.         DisposeRegion(this->ref);
  214.         this->ref = NULL;
  215.     }
  216.     if (!this->ref) nomem(this->o.g->io.win);
  217. }
  218.  
  219. /* Were we clicked on ? */
  220. static int down_label(struct label *this)
  221. {
  222.     struct graph *g = this->o.g;
  223.     WORD sx = ftol(g->io.rw->sx(g->io.rw, g->s.x));
  224.     WORD sy = ftol(g->io.rw->sy(g->io.rw, g->s.y));
  225.     int inside;
  226.  
  227.     calc_rect(this);
  228.     inside = sx >= this->lims.MinX && sx <= this->lims.MaxX &&
  229.              sy >= this->lims.MinY && sy <= this->lims.MaxY;
  230.     if (inside)
  231.     {
  232.         /* Setup internal info for move */
  233.         this->o.mx = sx - this->x0;
  234.         this->o.my = sy - this->y0;
  235.         if (alloc_bkgd_label(this))
  236.         {
  237.             save_bkgd_label(this);
  238.             if (this->selected)
  239.             {
  240.                 SetDrMd(&this->bkgd, COMPLEMENT);
  241.                 RectFill(&this->bkgd, 0, 0, this->bw - 1, this->bh - 1);
  242.             }
  243.             this->ref = NULL;
  244.             add_region(this); /* Original pos. will probably need refreshing */
  245.      
  246.             this->oldx = this->x; this->oldy = this->y;
  247.         }
  248.         else /* failed, no mem */
  249.         {
  250.             nomem(this->o.g->io.win);
  251.             inside = FALSE;
  252.         }
  253.     }
  254.     return inside;
  255. }
  256.  
  257. /* Reverse label's rectangle (eg for selection) */
  258. static void reverse_label(struct label *this)
  259. {
  260.     struct RastPort *rp = this->o.g->io.rw->rp;
  261.  
  262.     SetDrMd(rp, COMPLEMENT);
  263.     RectFill(rp, this->lims.MinX, this->lims.MinY, this->lims.MaxX, this->lims.
  264. MaxY);
  265. }
  266.  
  267. /* Draw label */
  268. static void draw_label(struct label *this, int allow_mes)
  269. {
  270.     struct graph *g = this->o.g;
  271.     struct RastPort *rp = g->io.rw->rp;
  272.     char *str;
  273.     int i;
  274.  
  275.     calc_rect(this);
  276.     SetAPen(rp, this->colour);
  277.     SetDrMd(rp, JAM1);
  278.     SetFont(rp, this->font);
  279.  
  280.     /* Draw all the lines of text */
  281.     Move(rp, this->lims.MinX - this->extent.MinX, this->lims.MinY - this->exten
  282. t.MinY + this->font->tf_Baseline);
  283.     for (str = this->broken, i = this->nblines; i; i--)
  284.     {
  285.         int l = strlen(str);
  286.  
  287.         Text(rp, str, l);
  288.         Move(rp, this->lims.MinX - this->extent.MinX, rp->cp_y + this->font->tf
  289. _YSize);
  290.  
  291.         str += l + 1; /* Onto next string */
  292.     }
  293.  
  294.     if (this->selected) reverse_label(this);
  295. }
  296.  
  297. /* We're now selected */
  298. static void select_label(struct label *this)
  299. {
  300.     this->selected = TRUE;
  301.     if (this->o.g->ok && this->o.g->io.rw)
  302.     {
  303.         calc_rect(this);
  304.         reverse_label(this);
  305.     }
  306. }
  307.  
  308. /* A quick walk around town ... */
  309. static void move_label(struct label *this)
  310. {
  311.     restore_bkgd_label(this); /* erase label */
  312.     this->x = this->o.g->s.x;
  313.     this->y = this->o.g->s.y;
  314.     calc_rect(this);
  315.     save_bkgd_label(this);    /* Save background */
  316.     draw_label(this, TRUE);   /* & draw at new pos */
  317. }
  318.  
  319. /* Mouse buttonb released, refresh needed ? */
  320. static struct Region *up_label(struct label *this)
  321. {
  322.     restore_bkgd_label(this); /* Restore at last pos */
  323.     this->x = this->o.g->s.x;
  324.     this->y = this->o.g->s.y;
  325.     calc_rect(this);
  326.     free_bkgd_label(this);
  327.     if (this->x != this->oldx || this->y != this->oldy) /* we moved */
  328.     {
  329.         add_region(this); /* Refresh at new pos */
  330.         return this->ref;
  331.     }
  332.     else
  333.     {
  334.         draw_label(this, TRUE); /* Just redraw, no refresh needed */
  335.         DisposeRegion(this->ref);
  336.         return NULL;
  337.     }
  338. }
  339.  
  340. /* End of selection, unhighlight */
  341. static struct Region *deselect_label(struct label *this)
  342. {
  343.     this->selected = FALSE;
  344.     if (this->o.g->ok && this->o.g->io.rw)
  345.     {
  346.         calc_rect(this);
  347.         reverse_label(this);
  348.     }
  349.     return NULL;
  350. }
  351.  
  352. /* Handle edit requester */
  353. int edit_handler(struct Gadget *gg, ULONG class, struct Requester *req, struct
  354. graph *g)
  355. {
  356.     if (gg->GadgetID == FONTLIST) /* User played with font list */
  357.     {
  358.         if (ModifyList(gg, req, req->RWindow, class == GADGETUP) == 2)
  359.         {
  360.             /* Double click -> exit */
  361.             EndRequest(req, req->RWindow);
  362.             return TRUE;
  363.         }
  364.         return FALSE;
  365.     }
  366.     else return std_ghandler(gg, class, req, g);
  367. }
  368.  
  369. /* Allow user to edit us */
  370. static int edit_label(struct label *this, struct Region **ref)
  371. {
  372.     struct Requester *req;
  373.     struct Memory *m;
  374.     struct Gadget *gl = NULL;
  375.     int ret = FALSE;
  376.     char text[LABELLEN], dx[NBLEN], dy[NBLEN], x[NBLEN], y[NBLEN], fname[FONTLE
  377. N], fheight[INTLEN], colour[INTLEN];
  378.     struct Gadget *leftg, *ctrxg, *rightg, *topg, *ctryg, *bottomg;
  379.  
  380.     this->ref = NULL;
  381.  
  382.     /* Create requester */
  383.     strcpy(text, this->text);
  384.     double2str(dx, this->dx);
  385.     double2str(dy, this->dy);
  386.     double2str(x, this->x);
  387.     double2str(y, this->y);
  388.     strcpy(fname, this->fname);
  389.     remfont(fname);
  390.     int2str(fheight, this->fheight);
  391.     int2str(colour, this->colour);
  392.  
  393.     if ((m = NewMemory()) &&
  394.         (req = InitReq(50, 15, 395, 166, m)) &&
  395.         SetReqBorder(req, 1, m) &&
  396.         AddIntuiText(&req->ReqText, "Edit Label", 158, 6, m) &&
  397.         AddText(&gl, 0, "Text ", FALSE, text, LABELLEN, TRUE, 0, RELVERIFY, 49,
  398.  20, 335, 10, TRUE, m) &&
  399.         AddText(&gl, 0, "X = ", FALSE, x, NBLEN, TRUE, 0, RELVERIFY, 43, 40, 56
  400. , 10, TRUE, m) &&
  401.         AddText(&gl, 0, "dX = ", FALSE, dx, NBLEN, TRUE, 0, RELVERIFY, 147, 40,
  402.  56, 10, TRUE, m) &&
  403.         (leftg = AddRadio(&gl, 0, "left", TRUE, SELECTED * (this->jx == top), R
  404. ELVERIFY, 16 + 32, 210, 40, 10, 10, m)) &&
  405.         (ctrxg = AddRadio(&gl, 0, "centre", TRUE, SELECTED * (this->jx == centr
  406. e), RELVERIFY, 8 + 32, 260, 40, 10, 10, m)) &&
  407.         (rightg = AddRadio(&gl, 0, "right", TRUE, SELECTED * (this->jx == botto
  408. m), RELVERIFY, 16 + 8, 326, 40, 10, 10, m)) &&
  409.         AddText(&gl, 0, "Y = ", FALSE, y, NBLEN, TRUE, 0, RELVERIFY, 43, 60, 56
  410. , 10, TRUE, m) &&
  411.         AddText(&gl, 0, "dY = ", FALSE, dy, NBLEN, TRUE, 0, RELVERIFY, 147, 60,
  412.  56, 10, TRUE, m) &&
  413.         (topg = AddRadio(&gl, 0, "top", TRUE, SELECTED * (this->jy == top), REL
  414. VERIFY, 512 + 1024, 210, 60, 10, 10, m)) &&
  415.         (ctryg = AddRadio(&gl, 0, "centre", TRUE, SELECTED * (this->jy == centr
  416. e), RELVERIFY, 256 + 1024, 260, 60, 10, 10, m)) &&
  417.         (bottomg = AddRadio(&gl, 0, "bottom", TRUE, SELECTED * (this->jy == bot
  418. tom), RELVERIFY, 256 + 512, 326, 60, 10, 10, m)) &&
  419.         AddText(&gl, 0, "Colour ", FALSE, colour, INTLEN, TRUE, 0, RELVERIFY, 2
  420. 36, 80, 32, 10, TRUE, m) &&
  421.         AddText(&gl, 0, "Size ", FALSE, fheight, INTLEN, TRUE, 0, RELVERIFY, 22
  422. 0, 150, 32, 10, TRUE, m) &&
  423.         AddList(&gl, FONTLIST, "Font", &flist, fname, FONTLEN, 0, RELVERIFY, 11
  424. , 80, 160, 80, TRUE, m) &&
  425.         AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 255, 100, 65, 15, FAL
  426. SE, m) &&
  427.         AddBox(&gl, FALSE, "Cancel", 0, RELVERIFY | ENDGADGET, 255, 130, 65, 15
  428. , FALSE, m))
  429.     {
  430.         SetReqGadgets(req, gl);
  431.         if (ret = DoRequest(req, this->o.g, edit_handler) && *stpblk(text) != '
  432. \0')
  433.         {
  434.             /* Update label */
  435.             double new;
  436.             int fh;
  437.             struct TextFont *newfont;
  438.  
  439.             add_region(this); /* Refresh needed at old pos */
  440.  
  441.             /* New justification, etc */
  442.             if ((this->colour = str2int(colour)) == INOVAL) this->colour = 1;
  443.             strcpy(this->text, text);
  444.             if ((new = str2double(x)) != NOVAL) this->x = new;
  445.             if ((new = str2double(y)) != NOVAL) this->y = new;
  446.             if ((this->dx = str2double(dx)) == NOVAL) this->dx = 0.0;
  447.             if ((this->dy = str2double(dy)) == NOVAL) this->dy = 0.0;
  448.  
  449.             if (leftg->Flags & SELECTED) this->jx = top;
  450.             else if (ctrxg->Flags & SELECTED) this->jx = centre;
  451.             else this->jx = bottom;
  452.  
  453.             if (topg->Flags & SELECTED) this->jy = top;
  454.             else if (ctryg->Flags & SELECTED) this->jy = centre;
  455.             else this->jy = bottom;
  456.  
  457.             /* Check font */
  458.             addfont(fname);
  459.             if ((fh = str2int(fheight)) == INOVAL || fh <= 0) fh = LABELHEIGHT;
  460.      
  461.             if (newfont = open_font(this->o.g, fname, fh, 0, 0))
  462.             {
  463.                 strcpy(this->fname, fname);
  464.                 this->fheight = fh;
  465.                 CloseFont(this->font);
  466.                 this->font = newfont;
  467.             }
  468.             else message(this->o.g, "Invalid font specified", (char *)NULL);
  469.  
  470.             /* Do precalculation */
  471.             setup_label(this);
  472.             calc_rect(this);
  473.             add_region(this); /* New position needs refreshing */
  474.         }
  475.     }
  476.     Free(m);
  477.     *ref = this->ref;
  478.     return ret;
  479. }
  480.  
  481. /* No vsriables used in labels */
  482. int var_change_label(struct label *this, char *name)
  483. {
  484.     return FALSE;
  485. }
  486.  
  487. /* Confirm changes made */
  488. static void confirm_label(struct label *this, int ok)
  489. {
  490.     if (ok)
  491.     {
  492.         CloseFont(this->font);
  493.         this->font = this->newfont;
  494.         setup_label(this);
  495.     }
  496.     else CloseFont(this->newfont); /* failed */
  497. }
  498.  
  499. /* Resolution has changed */
  500. static int inform_label(struct label *this, int ok)
  501. {
  502.     if (this->newfont = open_font(this->o.g, this->fname, this->fheight, 0, 0))
  503.      
  504.         return TRUE;
  505.  
  506.     message(this->o.g, "Couldn't open font", (char *)NULL);
  507.     return FALSE;
  508.  
  509. }
  510.  
  511. /* Write label to file */
  512. static int save_label(struct label *this, FILE *f)
  513. {
  514.     short tag = LABEL_TAG;
  515.     short end = LABEL_END;
  516.  
  517.     return WRITE(f, tag) &&
  518.            WRITE(f, this->text) &&
  519.            WRITE(f, this->colour) &&
  520.            WRITE(f, this->fname) &&
  521.            WRITE(f, this->fheight) &&
  522.            WRITE(f, this->x) &&
  523.            WRITE(f, this->y) &&
  524.            WRITE(f, this->dx) &&
  525.            WRITE(f, this->dy) &&
  526.            WRITE(f, end);
  527. }
  528.  
  529. /* free label */
  530. static struct Region *delete_label(struct label *this)
  531. {
  532.     struct Region *ref;
  533.  
  534.     /* Label's position will need refreshing */
  535.     this->ref = NULL;
  536.     if (this->o.g->ok && this->o.g->io.rw) add_region(this);
  537.     ref = this->ref;
  538.  
  539.     if (this->font) CloseFont(this->font);
  540.     FreeMem(this, sizeof(struct label));
  541.  
  542.     return ref;
  543. }
  544.  
  545. /* Initialise label structure */
  546. static struct label *make_label(struct graph *g)
  547. {
  548.     struct label *this = AllocMem(sizeof(struct label), 0L);
  549.     const static struct label def_l = {
  550.         {
  551.             { NULL },
  552.             NULL, "", TRUE, 0, 0,
  553.             (void *)delete_label, (void *)select_label, (void *)deselect_label,
  554.      
  555.             (void *)down_label, (void *)move_label, (void *)up_label,
  556.             (void *)edit_label, (void *)draw_label, (void *)notdone,
  557.             (void *)notdone, (void *)var_change_label, (void *)save_label,
  558.             (void *)inform_label, (void *)confirm_label
  559.         },
  560.         "", 1, LABELFONT, LABELHEIGHT, NOVAL, NOVAL, 0.0, 0.0, FALSE
  561.     };
  562.  
  563.     if (this)
  564.     {
  565.         *this = def_l;
  566.         this->o.g = g;
  567.         /* Default font *must* be there */
  568.         if (this->font = open_font(g, LABELFONT, LABELHEIGHT, 0, 0))
  569.         {
  570.             return this;
  571.         }
  572.         else
  573.             message(g, "Couldn't open font", (char *)NULL);
  574.         FreeMem(this, sizeof(struct label));
  575.     }
  576.     else
  577.         message(g, "No memory !", (char *)NULL);
  578.     return NULL;
  579. }
  580.  
  581. /* Load label from file */
  582. struct label *load_label(struct graph *g, FILE *f)
  583. {
  584.     struct label *this = make_label(g);
  585.  
  586.     if (this)
  587.     {
  588.         short tag;
  589.  
  590.         if (READ(f, this->text) &&
  591.             READ(f, this->colour) &&
  592.             READ(f, this->fname) &&
  593.             READ(f, this->fheight) &&
  594.             READ(f, this->x) &&
  595.             READ(f, this->y) &&
  596.             READ(f, this->dx) &&
  597.             READ(f, this->dy) &&
  598.             READ(f, tag) &&
  599.             tag == LABEL_END)
  600.         {
  601.             struct TextFont *newfont;
  602.  
  603.             if (newfont = open_font(this->o.g, this->fname, this->fheight, 0, 0
  604. ))
  605.             {
  606.                 CloseFont(this->font);
  607.                 this->font = newfont;
  608.             }
  609.             else /* Lack of font isn't drastic */
  610.             {
  611.                 message(g, "No such font available", this->fname, (char *)NULL)
  612. ;
  613.                 strcpy(this->fname, LABELFONT);
  614.             }
  615.             setup_label(this);
  616.             return this;
  617.         }
  618.         delete_label(this);
  619.     }
  620.     return NULL;
  621. }
  622.  
  623. /* Create a new label, at pos. (x,y). Asks user for text */
  624. struct label *new_label(struct graph *g, double x, double y)
  625. {
  626.     struct label *this = make_label(g);
  627.  
  628.     if (this)
  629.     {
  630.         /* Create requester */
  631.         struct Requester *req;
  632.         struct Memory *m;
  633.         struct Gadget *gl = NULL;
  634.         int ret = FALSE;
  635.  
  636.         this->x = x;
  637.         this->y = y;
  638.  
  639.         if ((m = NewMemory()) &&
  640.             (req = InitReq(50, 20, 160, 65, m)) &&
  641.             SetReqBorder(req, 1, m) &&
  642.             AddIntuiText(&req->ReqText, "Add Label", 44, 6, m) &&
  643.             AddText(&gl, TRUE, "Text ", FALSE, this->text, LABELLEN, TRUE, 0, R
  644. ELVERIFY | ENDGADGET, 49, 20, 100, 10, TRUE, m) &&
  645.             AddBox(&gl, TRUE, "Ok", 0, RELVERIFY | ENDGADGET, 8, 40, 65, 15, FA
  646. LSE, m) &&
  647.             AddBox(&gl, FALSE, "Cancel", 0, RELVERIFY | ENDGADGET, 88, 40, 65,
  648. 15, FALSE, m))
  649.         {
  650.             SetReqGadgets(req, gl);
  651.             if (ret = DoRequest(req, g, std_ghandler) && *stpblk(this->text) !=
  652.  '\0')
  653.             {
  654.                 /* Create it */
  655.                 setup_label(this);
  656.                 if (g->ok && g->io.rw) draw_label(this, TRUE);
  657.                 Free(m);
  658.                 return this;
  659.             }
  660.         }
  661.         Free(m);
  662.         delete_label(this);
  663.     }
  664.     else
  665.         message(g, "No memory !", (char *)NULL);
  666.     return NULL;
  667. }
  668.  
  669.