/*
 *	$Source: /u1/X/DECToolkit/src/RCS/Label.c,v $
 *	$Header: Label.c,v 1.1 86/12/17 09:02:13 swick Exp $
 */

#ifndef lint
static char *rcsid_Label_c = "$Header: Label.c,v 1.1 86/12/17 09:02:13 swick Exp $";
#endif	lint

#ifndef lint
static  char    *sccsid = "@(#)Label.c	1.10          12/11/86";
#endif lint
/*
 *			  COPYRIGHT 1986
 *		   DIGITAL EQUIPMENT CORPORATION
 *		       MAYNARD, MASSACHUSETTS
 *			ALL RIGHTS RESERVED.
 *
 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
 * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
 *
 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
 * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
 * SET FORTH ABOVE.
 *
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting documentation,
 * and that the name of Digital Equipment Corporation not be used in advertising
 * or publicity pertaining to distribution of the software without specific, 
 * written prior permission.
 */


/* File: Label.c */


#include <X/Xlib.h>
#include <strings.h>
#include "Toolkit.h"

/* Private Definitions */

#define DEFAULT_LABEL "Label "
#define DEFAULT_FONT  "/usr/lib/Xfont/9x15.onx"
#define myEvents ExposeWindow

/***
 *** Label data structure.
 ***/
typedef struct _LabelData {
    Window w;		/* label window */
    char *label;	/* string in label */
    FontInfo *font;	/* font used       */
    int width, height,  /* width and height in pixels of window */
	lwidth; 	/* width in pixels of string in label */
    int foregroundcolor;
    int justify;	/* -1 = left justify string
			    0 = center string
			    1 = right justify string; */
} LabelData, *LabelPtr;	

static int initDone = 0;
static TEntryType LabelEntry;
static FontInfo *default_font;

/*********************** private procedures *************************/

/***
 *** On first create of label, find a unique entry type for labels.
 ***/
static Initialize()
{
    LabelEntry = UniqueEntryType();
    initDone = 1;
    default_font = XOpenFont(DEFAULT_FONT);
}


/***
 ***  finds the label data structure associated with the given window.
 ***/
static LabelPtr LabelPtrFromWindow(window)
Window window;
{
    LabelPtr result;
    if (FindEntry(window, LabelEntry, &result) == ERRNONE) return result;
    return 0;
}


/***
 ***  This routine performs the X call to put the text into the window.
 ***/
static PutLabelText (data)
LabelPtr data;
{
    int leftmargin, topmargin;

    switch (data->justify) {
    case -1:
        leftmargin = xMargin;
        break;
    case 0:
    default:
        leftmargin = (data->width - data->lwidth) / 2;
        break;
    case 1:
        leftmargin = data->width - (data->lwidth + xMargin);
        break;
    }
    topmargin = (data->height - data->font->height) / 2;
    XTextMask(data->w, leftmargin, topmargin,
            data->label, strlen(data->label),
            data->font->id, data->foregroundcolor);
}

/***************** Semi-public procedures ********************/

/***
 *** routine to handle all events on the label window.
 ***/
static int HandleEvents(event)
XExposeWindowEvent *event;
{
    int     returnCode, leftmargin, topmargin;
    LabelPtr ctx;

    ctx = LabelPtrFromWindow(event->window);
    if (!ctx)
        return(NOTHANDLED);
    returnCode = PROCESSED;
    switch (event->type) {
        case ResizeWindow: 
            ctx->width = event->width;
            ctx->height = event->height;
	    XClear(ctx->w);
            PutLabelText (ctx);
            break;
        case ExposeWindow: 
	    if (ctx->width  != ((XExposeWindowEvent *) event)->width ||
	        ctx->height != ((XExposeWindowEvent *) event)->height) {
		    ctx->width = ((XExposeWindowEvent *) event)->width;
		    ctx->height = ((XExposeWindowEvent *) event)->height;
		    XClear(ctx->w);
	    }
            PutLabelText (ctx);
            break;
        default: 
            returnCode = NOTHANDLED;
    }
    return returnCode;
}


/***
 *** given a label and a string, this routine puts the new string into
 *** the label.  NOTE: it does NOT resize the label.
 ***/
ChangeLabelText (ctx, string)
    LabelPtr ctx;          /* window id of label tool */
    char *string;           /* new string to be displayed as label */
{
    if (ctx) {
        free(ctx->label);
        ctx->label = strcpy(Tmalloc(strlen(string) + 1), string);
        ctx->lwidth = XStringWidth(ctx->label, ctx->font, 0, 0);
        XClear (ctx->w);
        PutLabelText (ctx);
    }
}

ChangeLabelWidth(ctx, width)
    LabelPtr ctx;
    int width;
{
    if (ctx) {
	if (width == 0) return;
        ctx->width = width;
        XChangeWindow(ctx->w, ctx->width, ctx->height); 
   	XClear(ctx->w);
   	PutLabelText(ctx);
    }
}

ChangeLabelHeight(ctx, height)
    LabelPtr ctx;
    int height;
{
    if (ctx) {
	if (height == 0) return;
	ctx->height = height;
	XChangeWindow(ctx->w, ctx->width, ctx->height);
	XClear(ctx->w);
	PutLabelText(ctx);
    }
}

ChangeLabelJustify(ctx, justify)
    LabelPtr ctx;
    int justify;
{
    if (ctx) {
	ctx->justify = justify;
	XClear(ctx->w);
	PutLabelText(ctx);
    }
}

/************************* Public routines. *******************/

/***
 *** Creates a label tool and returns window id
 ***/
Window TCreateLabel (pw, arglist)
  Window pw;		/** parent window **/
  Targ   *arglist;
{
    LabelPtr ctx;
    int x, y;               /* offset of top, left of label in parent */ 
    int borderWidth;

    if (!initDone) Initialize();
    ctx = (LabelPtr) Tmalloc(sizeof(LabelData));

    /*** 
     *** assign defaults.
     ***/
    ctx->label = strcpy(Tmalloc(strlen(DEFAULT_LABEL) +1), DEFAULT_LABEL);
    ctx->foregroundcolor = BlackPixel;
    ctx->justify = 0;
    ctx->font = default_font;
    ctx->width = 0;
    ctx->height = 0;
    borderWidth = 1;
    x = y = 0;
    
    /***
     *** Parse input parameters.
     ***/
    while (arglist->name) {
	switch (arglist->name) {
	case T_LABEL_STRING:
	   ctx->label = strcpy(Tmalloc(strlen((char *) arglist->data) +1),
			       (char *) arglist->data);
	   break;
	case T_LABEL_FONTINFO:
	   ctx->font = (FontInfo *) arglist->data;
	   break;
	case T_LABEL_WIDTH:
	   ctx->width = abs((int)arglist->data);
	   break;
	case T_LABEL_HEIGHT:
	   ctx->height = abs((int)arglist->data);
	   break;
	case T_LABEL_JUSTIFY:
	   ctx->justify = (int) arglist->data;
	   break;
	case T_LABEL_BORDERWIDTH:
	   borderWidth = (int) arglist->data;
	   break;
	case T_LABEL_FOREGROUND_PIXEL:
	   ctx->foregroundcolor = (int) arglist->data;
	   break;
	}
	arglist++;
    }

    /*** 
     *** finish up defaults.
     ***/
    if (ctx->width == NULL)
        ctx->width = XStringWidth(ctx->label, ctx->font, 0, 0) + 2 * xMargin;
    if (ctx->height == NULL) 
	ctx->height = ctx->font->height + 2 * yMargin;
    ctx->lwidth = XStringWidth(ctx->label, ctx->font, 0, 0);
    
    /***
     *** create the window.
     ***/
    ctx->w = XCreateWindow( pw, x, y, ctx->width, ctx->height, 
            		    borderWidth, BlackPixmap, WhitePixmap);

    SaveEntry(ctx->w, LabelEntry , ctx);
    TSetXEventDispatch(ctx->w, HandleEvents, myEvents, 0);
    return (ctx->w);
}


/***
 *** This routine lets the application change the attributes of the 
 *** label tool.  
 *** NOTE: currently you may only change the text withing the label.
 ***       This does NOT cause the label to be resized.
 ***/
TSetLabelAttr(tw, arglist)
Window tw;              /* tool window */
Targ *arglist;
{
    LabelPtr ctx;
    ctx = LabelPtrFromWindow(tw);

    while (arglist->name) {
	switch (arglist->name) {
	case T_LABEL_STRING:
	   ChangeLabelText(ctx, (char *) arglist->data);
	   break;
	case T_LABEL_FONTINFO:
	   break;
	case T_LABEL_WIDTH:
	   ChangeLabelWidth(ctx, abs((int)arglist->data));
	   break;
	case T_LABEL_HEIGHT:
	   ChangeLabelHeight(ctx, abs((int)arglist->data));
	   break;
	case T_LABEL_JUSTIFY:
	   ChangeLabelJustify(ctx, (int) arglist->data);
	   break;
	case T_LABEL_BORDERWIDTH:
	   break;
	case T_LABEL_FOREGROUND_PIXEL:
	   break;
	}
	arglist++;
    }
}


/***
 *** This routine lets the application get the attributes of the given
 *** label tool. 
 ***/
TGetLabelAttr(tw, arglist)
    Window tw;	/* tool window */
    Targ  *arglist; 
{
    WindowInfo info;
    LabelPtr ctx;
    ctx = LabelPtrFromWindow(tw);

    /***
     *** Parse input parameters.
     ***/
    while (arglist->name) {
	switch (arglist->name) {
	case T_LABEL_STRING:
	   arglist->data = (caddr_t) ctx->label;
	   break;
	case T_LABEL_FONTINFO:
	   arglist->data = (caddr_t) ctx->font;
	   break;
	case T_LABEL_WIDTH:
	   arglist->data = (caddr_t) ctx->width;
	   break;
	case T_LABEL_HEIGHT:
	   arglist->data = (caddr_t) ctx->height;
	   break;
	case T_LABEL_JUSTIFY:
	   arglist->data = (caddr_t) ctx->justify;
	   break;
	case T_LABEL_BORDERWIDTH:
	   XQueryWindow(ctx->w, &info);
	   arglist->data = (caddr_t) info.bdrwidth;
	   break;
	case T_LABEL_FOREGROUND_PIXEL:
	   arglist->data = (caddr_t) ctx->foregroundcolor;
	   break;
	}
	arglist++;
    }
}


/***
 *** Destroys the label tool associated with the window as well as the
 *** window itself
 ***/
TDestroyLabel (window)
Window window;          /* window id of label tool */
{
    LabelPtr ctx;
    ctx = LabelPtrFromWindow(window);
    if (ctx) {
        free(ctx->label);
        free(ctx);
        DeleteEntry(window, LabelEntry);
	TDestroyWindow(window);
    }
    XDestroyWindow (window);
}
