/*
 * Copyright (C) 1992 by Software Research Associates, Inc.
 *      Author: Y. Kawabe <kawabe@sra.co.jp>
 *
 * Permission to use, copy, modify, and distribute, and sell 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 Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  Software Research Associates
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 */

/*
 * Multi-Byte String Label
 */

#include <InterViews/wlabel.h>
#include <InterViews/coord.h>
#include <InterViews/canvas.h>
#include <InterViews/color.h>
#include <InterViews/font.h>
#include <InterViews/fontset.h>
#include <InterViews/hit.h>
#include <NLS/charset.h>
#include <NLS/wchar.h>
#include <NLS/wstring.h>
#include <string.h>

WLabel::WLabel (
    const WString& wstr, const FontSet *fs, const Color *c
) : Glyph() {
    text_ = new CopyWString(wstr);
    fontset_ = fs;
    Resource::ref(fontset_);
    color_ = c;
    Resource::ref(color_);

    FontBoundingBox b;
    fs->string_bbox(text_->string(), text_->length(), b);
    ascent_ = b.font_ascent();
    descent_ = b.font_descent();
    left_ = b.left_bearing();
    right_ = b.right_bearing();
    width_ = b.width();

    const FontSetRep* rep;
    CharSet_T charset = CharSet::ascii();
    const Font *fn = fontset_->Find(charset, rep);
    int len = text_->length();
    widths_ = new Coord[len];

    for (int i = 0; i < len ; i++) {
	if ((*text_)[i].charset() != charset) {
	    charset = (*text_)[i].charset();
	    fn = fontset_->Find(charset, rep);
	}
	widths_[i] = fn ? fn->width(rep->convert((*text_)[i].charcode())) : 0;
    }
}

WLabel::~WLabel() {
    delete text_;
    delete widths_;
    Resource::unref(fontset_);
    Resource::unref(color_);
}

void WLabel::request(Requisition& requisition) const {
    Coord height = ascent_ + descent_;
    float alignment = (height == 0) ? 0 : descent_ / height;
    Requirement rx(width_, 0, 0, 0);
    Requirement ry(height, 0, 0, alignment);
    requisition.require(Dimension_X, rx);
    requisition.require(Dimension_Y, ry);
}

void WLabel::allocate(Canvas* c, const Allocation& a, Extension& ext) {
    Coord x = a.x();
    Coord y = a.y();
    ext.set_xy(c, x - left_, y - descent_, x + right_, y + ascent_);
}

void WLabel::draw(Canvas* canvas, const Allocation& a) const {
    Coord x = a.x();
    Coord y = a.y();

    int len = text_->length();
    const FontSetRep* rep;
    CharSet_T charset = CharSet::ascii();
    const Font *fn = fontset_->Find(charset, rep);
    const Color* c = color_;

    for (int i = 0; i < len ; i++) {
	if ((*text_)[i].charset() != charset) {
	    charset = (*text_)[i].charset();
	    fn = fontset_->Find(charset, rep);
	}
	if (fn) {
	    canvas->character(fn, rep->convert((*text_)[i].charcode()),
			      widths_[i], c, x, y);
	    x += widths_[i];
	}
    }
}

void WLabel::pick(Canvas*, const Allocation& a, int depth, Hit& h) {
    Coord x = h.left();
    Coord y = h.bottom();
    
    if (x >= a.left() && x < a.right() && y >= a.bottom() && y < a.top()) {
        int index = fontset_->index(text_->string(), text_->length(),
				 x - a.x(), true);
        h.target(depth, this, index);
    }
}

