зеркало из https://github.com/mozilla/pjs.git
847 строки
21 KiB
C
847 строки
21 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "xp.h"
|
|
#include "layout.h"
|
|
#include "laylayer.h"
|
|
#include "libi18n.h"
|
|
#include "xlate.h"
|
|
#include "layers.h"
|
|
|
|
#define IL_CLIENT /* XXXM12N Defined by Image Library clients */
|
|
#include "libimg.h" /* Image Library public API. */
|
|
|
|
#ifdef PROFILE
|
|
#pragma profile on
|
|
#endif
|
|
|
|
#ifdef XP_MAC
|
|
# ifdef XP_TRACE
|
|
# undef XP_TRACE
|
|
# endif
|
|
# define XP_TRACE(X)
|
|
#else
|
|
#ifndef XP_TRACE
|
|
# define XP_TRACE(X) fprintf X
|
|
#endif
|
|
#endif /* XP_MAC */
|
|
|
|
|
|
/*
|
|
* BUGBUG LAYERS: This is a hack that is currently being used for selection
|
|
* but might be useful elsewhere. Essentially, for extending the selected
|
|
* text, we know exactly how much we want to draw (using FE_DisplaySubtext).
|
|
* Rather than ask for a synchronous refresh of the area and relying on
|
|
* LO_RefreshArea to do the correct drawing (actually, it can't do the
|
|
* correct drawing since it doesn't draw sub-strings), we temporarily replace
|
|
* the painter_func for the layer in question to one that just does the
|
|
* required drawing. We still do a synchronous refresh, but the temporary
|
|
* painter_func is called instead of the one that calls LO_RefreshArea.
|
|
*/
|
|
typedef struct LO_SelectionHackStruct {
|
|
MWContext *context;
|
|
LO_TextStruct *text;
|
|
int32 start_pos;
|
|
int32 end_pos;
|
|
Bool need_bg;
|
|
} LO_SelectionHackStruct;
|
|
|
|
static void
|
|
lo_selection_hack_painter_func(void *drawable,
|
|
CL_Layer *layer,
|
|
FE_Region update_region)
|
|
{
|
|
LO_SelectionHackStruct *hack = (LO_SelectionHackStruct *)CL_GetLayerClientData(layer);
|
|
|
|
FE_SetDrawable(hack->context, drawable);
|
|
|
|
/* For layers, we don't ever need to clear the background */
|
|
FE_DisplaySubtext(hack->context, FE_VIEW,
|
|
hack->text, hack->start_pos, hack->end_pos,
|
|
FALSE);
|
|
|
|
FE_SetDrawable(hack->context, NULL);
|
|
}
|
|
|
|
static void
|
|
lo_NormalizeStartAndEndOfSelection(LO_TextStruct *text, int32 *start,
|
|
int32 *end)
|
|
{
|
|
int32 p1, p2;
|
|
char *string;
|
|
int n;
|
|
int16 charset;
|
|
|
|
if (text->ele_attrmask & LO_ELE_SELECTED)
|
|
{
|
|
if (text->sel_start < 0)
|
|
{
|
|
p1 = 0;
|
|
}
|
|
else
|
|
{
|
|
p1 = text->sel_start;
|
|
}
|
|
|
|
if (text->sel_end < 0)
|
|
{
|
|
p2 = text->text_len - 1;
|
|
}
|
|
else
|
|
{
|
|
p2 = text->sel_end;
|
|
}
|
|
|
|
PA_LOCK(string, char *, text->text);
|
|
|
|
/*
|
|
* find beginning of first character
|
|
*/
|
|
charset = text->text_attr->charset;
|
|
switch (n = INTL_NthByteOfChar(charset, string, (int)(p1+1)))
|
|
{
|
|
case 0:
|
|
case 1:
|
|
break;
|
|
default:
|
|
p1 -= (n - 1);
|
|
if (p1 < 0)
|
|
{
|
|
p1 = 0;
|
|
}
|
|
break;
|
|
}
|
|
if (text->sel_start >= 0)
|
|
{
|
|
text->sel_start = p1;
|
|
}
|
|
|
|
/*
|
|
* find end of last character
|
|
*/
|
|
switch (n = INTL_NthByteOfChar(charset, string, (int)(p2+1)))
|
|
{
|
|
case 0:
|
|
break;
|
|
default:
|
|
p2 -= (n - 1);
|
|
if (p2 < 0)
|
|
{
|
|
p2 = 0;
|
|
}
|
|
/* fall through */
|
|
case 1:
|
|
p2 += INTL_IsLeadByte(charset, string[p2]);
|
|
if (p2 > text->text_len - 1)
|
|
{
|
|
p2 = text->text_len - 1;
|
|
}
|
|
break;
|
|
}
|
|
if (text->sel_end >= 0)
|
|
{
|
|
text->sel_end = p2;
|
|
}
|
|
|
|
*start = p1;
|
|
*end = p2;
|
|
|
|
PA_UNLOCK(text->text);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
LO_DUMP_RECT(XP_Rect *rect)
|
|
{
|
|
XP_TRACE(("Compositing rectangle: [%3d,%3d] %d x %d\n", rect->left, rect->top,
|
|
rect->right - rect->left, rect->bottom - rect->top));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* BUGBUG LAYERS: Since we know that lo_DisplaySubtext is only done
|
|
* for selection, we generate a synchronous composite. This might
|
|
* not be the right thing to do: maybe we should have an additional
|
|
* argument to the LO_Display routines
|
|
*/
|
|
void
|
|
lo_DisplaySubtext(MWContext *context, LO_TextStruct *text,
|
|
int32 start_pos, int32 end_pos, Bool need_bg,
|
|
CL_Layer *sel_layer)
|
|
{
|
|
lo_NormalizeStartAndEndOfSelection(text, &start_pos, &end_pos);
|
|
/* If we have to draw, go through the compositor */
|
|
if (context->compositor) {
|
|
XP_Rect rect;
|
|
CL_Layer *layer;
|
|
int32 x_offset, y_offset;
|
|
|
|
if (!sel_layer)
|
|
layer = CL_FindLayer(context->compositor, LO_BODY_LAYER_NAME);
|
|
else
|
|
layer = sel_layer;
|
|
|
|
FE_GetTextFrame(context, text, start_pos, end_pos, &rect);
|
|
lo_GetLayerXYShift(layer, &x_offset, &y_offset);
|
|
XP_OffsetRect(&rect, -x_offset, -y_offset);
|
|
|
|
CL_UpdateLayerRect(context->compositor, layer, &rect, PR_FALSE);
|
|
|
|
return;
|
|
}
|
|
else
|
|
/* For layers, we don't ever need to clear the background */
|
|
FE_DisplaySubtext(context, FE_VIEW, text, start_pos, end_pos,
|
|
FALSE);
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayText(MWContext *context,
|
|
LO_TextStruct *text, Bool need_bg)
|
|
{
|
|
int32 p1, p2;
|
|
LO_TextAttr tmp_attr;
|
|
LO_TextAttr *hold_attr;
|
|
|
|
/* Blinking text elements are placed in a separate layer */
|
|
if (context->compositor && text->text_attr->attrmask & LO_ATTR_BLINK)
|
|
{
|
|
if (! (text->ele_attrmask & LO_ELE_DRAWN))
|
|
{
|
|
/* XXX - If the BLINK is in a layer, we need to create the
|
|
blink layer as a child of that layer, not as a child of
|
|
the _BODY layer. */
|
|
CL_Layer *body_layer =
|
|
CL_FindLayer(context->compositor, LO_BODY_LAYER_NAME);
|
|
lo_CreateBlinkLayer(context, text, body_layer);
|
|
text->ele_attrmask |= LO_ELE_DRAWN;
|
|
}
|
|
|
|
/* All blink text drawing is handled by the blink layer's
|
|
painter function. Don't do any drawing here. */
|
|
return;
|
|
}
|
|
|
|
if (text->ele_attrmask & LO_ELE_SELECTED)
|
|
{
|
|
lo_NormalizeStartAndEndOfSelection(text, &p1, &p2);
|
|
|
|
if (p1 > 0)
|
|
{
|
|
/* For layers we don't ever need to clear the background */
|
|
FE_DisplaySubtext(context, FE_VIEW, text,
|
|
0, (p1 - 1), FALSE);
|
|
}
|
|
|
|
lo_CopyTextAttr(text->text_attr, &tmp_attr);
|
|
tmp_attr.fg.red = text->text_attr->bg.red;
|
|
tmp_attr.fg.green = text->text_attr->bg.green;
|
|
tmp_attr.fg.blue = text->text_attr->bg.blue;
|
|
tmp_attr.bg.red = text->text_attr->fg.red;
|
|
tmp_attr.bg.green = text->text_attr->fg.green;
|
|
tmp_attr.bg.blue = text->text_attr->fg.blue;
|
|
|
|
/* lo_CopyTextAttr doesn't copy the FE_Data. In
|
|
* this case, however, we need to copy the FE_Data
|
|
* because otherwise the front end will
|
|
* synthesize a new copy. This assumes that
|
|
* the FE_Data doesn't care about font color.
|
|
*/
|
|
tmp_attr.FE_Data = text->text_attr->FE_Data;
|
|
|
|
hold_attr = text->text_attr;
|
|
text->text_attr = &tmp_attr;
|
|
/* For layers we don't ever need to clear the background */
|
|
FE_DisplaySubtext(context, FE_VIEW, text, p1, p2,
|
|
FALSE);
|
|
text->text_attr = hold_attr;
|
|
|
|
if (p2 < (text->text_len - 1))
|
|
{
|
|
/* For layers we don't ever need to clear the background */
|
|
FE_DisplaySubtext(context, FE_VIEW, text,
|
|
(p2 + 1), (text->text_len - 1),
|
|
FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* For layers we don't ever need to clear the background */
|
|
FE_DisplayText(context, FE_VIEW, text, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayEmbed(MWContext *context, LO_EmbedStruct *embed)
|
|
{
|
|
CL_Layer *layer;
|
|
|
|
if (! context->compositor) {
|
|
FE_DisplayEmbed(context, FE_VIEW, embed);
|
|
return;
|
|
}
|
|
|
|
/* Don't ever display hidden embeds */
|
|
if (embed->objTag.ele_attrmask & LO_ELE_HIDDEN)
|
|
return;
|
|
|
|
layer = embed->objTag.layer;
|
|
XP_ASSERT(layer);
|
|
if (! layer) /* Paranoia */
|
|
return;
|
|
|
|
if (!(embed->objTag.ele_attrmask & LO_ELE_DRAWN)) {
|
|
/* Move layer to new position */
|
|
CL_MoveLayer(layer,
|
|
embed->objTag.x + embed->objTag.x_offset,
|
|
embed->objTag.y + embed->objTag.y_offset);
|
|
CL_SetLayerHidden(layer, PR_FALSE);
|
|
embed->objTag.ele_attrmask |= LO_ELE_DRAWN;
|
|
}
|
|
}
|
|
|
|
void
|
|
lo_DisplayBuiltin(MWContext *context, LO_BuiltinStruct *builtin)
|
|
{
|
|
CL_Layer *layer;
|
|
|
|
/* need to deal with layers here XXX */
|
|
|
|
if (! context->compositor) {
|
|
FE_DisplayBuiltin(context, FE_VIEW, builtin);
|
|
return;
|
|
}
|
|
|
|
layer = builtin->layer;
|
|
XP_ASSERT(layer);
|
|
if (! layer) /* Paranoia */
|
|
return;
|
|
|
|
if (!(builtin->ele_attrmask & LO_ELE_DRAWN)) {
|
|
/* Move layer to new position */
|
|
CL_MoveLayer(layer,
|
|
builtin->x + builtin->x_offset,
|
|
builtin->y + builtin->y_offset);
|
|
CL_SetLayerHidden(layer, PR_FALSE);
|
|
builtin->ele_attrmask |= LO_ELE_DRAWN;
|
|
}
|
|
}
|
|
|
|
#ifdef JAVA
|
|
void
|
|
lo_DisplayJavaApp(MWContext *context, LO_JavaAppStruct *java_app)
|
|
{
|
|
CL_Layer *layer;
|
|
|
|
if (! context->compositor) {
|
|
FE_DisplayJavaApp(context, FE_VIEW, java_app);
|
|
return;
|
|
}
|
|
|
|
layer = java_app->objTag.layer;
|
|
XP_ASSERT(layer);
|
|
if (! layer) /* Paranoia */
|
|
return;
|
|
|
|
if (!(java_app->objTag.ele_attrmask & LO_ELE_DRAWN)) {
|
|
/* Move layer to new position */
|
|
CL_MoveLayer(layer,
|
|
java_app->objTag.x + java_app->objTag.x_offset,
|
|
java_app->objTag.y + java_app->objTag.y_offset);
|
|
|
|
/* Now that layer is layed out to its final position,
|
|
we can display it */
|
|
CL_SetLayerHidden(layer, PR_FALSE);
|
|
java_app->objTag.ele_attrmask |= LO_ELE_DRAWN;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Make the image layer visible and draw the image border. Should only be called
|
|
if there is a compositor. */
|
|
static void
|
|
lo_DisplayImage(MWContext *context, LO_ImageStruct *image)
|
|
{
|
|
int bw = image->border_width;
|
|
|
|
XP_ASSERT(context->compositor);
|
|
|
|
/* Allow the compositor to start drawing the image layer. */
|
|
lo_ActivateImageLayer(context, image);
|
|
|
|
/* The image border, if present, draws in the parent of the image layer. */
|
|
if (bw) {
|
|
int x = image->x + image->x_offset + bw;
|
|
int y = image->y + image->y_offset + bw;
|
|
|
|
FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw,
|
|
image->width + 2 * bw, image->height + 2 * bw, bw,
|
|
&image->text_attr->fg, LO_SOLID);
|
|
}
|
|
}
|
|
|
|
void
|
|
lo_DisplayImageWithoutCompositor(MWContext *context, LO_ImageStruct *image)
|
|
{
|
|
int bw = image->border_width;
|
|
int x = image->x + image->x_offset + bw;
|
|
int y = image->y + image->y_offset + bw;
|
|
int width = image->width;
|
|
int height = image->height;
|
|
|
|
/* This routine should only be called in the absence of a compositor. */
|
|
XP_ASSERT(!context->compositor);
|
|
|
|
/* Handle the TextFE. */
|
|
if (context->type == MWContextText) {
|
|
XL_DisplayTextImage(context, FE_VIEW, image);
|
|
return;
|
|
}
|
|
|
|
if (image->is_icon) {
|
|
IL_DisplayIcon(context->img_cx, image->icon_number, x, y);
|
|
}
|
|
else {
|
|
int cnv_x = context->convertPixX;
|
|
int cnv_y = context->convertPixY;
|
|
|
|
IL_DisplaySubImage(image->image_req, x/cnv_x, y/cnv_y, 0, 0,
|
|
width/cnv_x, height/cnv_y);
|
|
}
|
|
|
|
if (bw)
|
|
FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw, width + 2 * bw,
|
|
height + 2 * bw, bw, &image->text_attr->fg, LO_SOLID);
|
|
}
|
|
|
|
void
|
|
lo_DisplaySubImageWithoutCompositor(MWContext *context, LO_ImageStruct *image,
|
|
int32 x, int32 y, uint32 width, uint32 height)
|
|
{
|
|
int bw = image->border_width;
|
|
int x_pos = image->x + image->x_offset + bw;
|
|
int y_pos = image->y + image->y_offset + bw;
|
|
int sub_x, sub_y, sub_w, sub_h;
|
|
|
|
/* This routine should only be called in the absence of a compositor. */
|
|
XP_ASSERT(!context->compositor);
|
|
|
|
/* Handle the TextFE. */
|
|
if (context->type == MWContextText) {
|
|
XL_DisplayTextImage(context, FE_VIEW, image);
|
|
return;
|
|
}
|
|
|
|
if (x < x_pos) {
|
|
sub_x = x_pos;
|
|
sub_w = width + x - x_pos;
|
|
}
|
|
else {
|
|
sub_x = x;
|
|
sub_w = width;
|
|
}
|
|
|
|
if (y < y_pos) {
|
|
sub_y = y_pos;
|
|
sub_h = height + y - y_pos;
|
|
}
|
|
else {
|
|
sub_y = y;
|
|
sub_h = height;
|
|
}
|
|
|
|
if (x + width > x_pos + image->width)
|
|
sub_w += (x_pos + image->width - x - width);
|
|
|
|
if (y + height > y_pos + image->height)
|
|
sub_h += (y_pos + image->height - y - height);
|
|
|
|
if (sub_w > 0 && sub_h > 0) {
|
|
if (image->is_icon) {
|
|
IL_DisplayIcon(context->img_cx, image->icon_number,
|
|
x_pos, y_pos);
|
|
}
|
|
else {
|
|
int cnv_x = context->convertPixX;
|
|
int cnv_y = context->convertPixY;
|
|
|
|
IL_DisplaySubImage(image->image_req, x_pos/cnv_x, y_pos/cnv_y,
|
|
(sub_x - x_pos)/cnv_x, (sub_y - y_pos)/cnv_y,
|
|
sub_w/cnv_x, sub_h/cnv_y);
|
|
}
|
|
}
|
|
|
|
if (bw)
|
|
FE_DisplayBorder(context, FE_VIEW, x - bw, y - bw, width + 2 * bw,
|
|
height + 2 * bw, bw, &image->text_attr->fg,
|
|
LO_SOLID);
|
|
}
|
|
|
|
/* Should only be called in the absence of a compositor. */
|
|
void
|
|
lo_ClipImage(MWContext *context, LO_ImageStruct *image,
|
|
int32 x, int32 y, uint32 width, uint32 height)
|
|
{
|
|
int32 sub_x, sub_y;
|
|
uint32 sub_w, sub_h;
|
|
|
|
/*
|
|
* If the two don't overlap, do nothing.
|
|
*/
|
|
if (((int32)(image->x + image->x_offset + image->width +
|
|
2*image->border_width) < x)||
|
|
((int32)(x + width) < (int32)(image->x + image->x_offset))||
|
|
((int32)(image->y + image->y_offset + image->height +
|
|
2*image->border_width) < y)||
|
|
((int32)(y + height) < (int32)(image->y + image->y_offset)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((image->x + image->x_offset) >= x)
|
|
{
|
|
sub_x = image->x + image->x_offset;
|
|
}
|
|
else
|
|
{
|
|
sub_x = x;
|
|
}
|
|
|
|
if ((int32)(image->x + image->x_offset + image->width + 2*image->border_width)
|
|
<= (int32)(x + width))
|
|
{
|
|
sub_w = image->x + image->x_offset + image->width +
|
|
2*image->border_width - sub_x;
|
|
}
|
|
else
|
|
{
|
|
sub_w = x + width - sub_x;
|
|
}
|
|
|
|
if ((image->y + image->y_offset) >= y)
|
|
{
|
|
sub_y = image->y + image->y_offset;
|
|
}
|
|
else
|
|
{
|
|
sub_y = y;
|
|
}
|
|
|
|
if ((int32)(image->y + image->y_offset + image->height + 2*image->border_width)
|
|
<= (int32)(y + height))
|
|
{
|
|
sub_h = image->y + image->y_offset + image->height +
|
|
2*image->border_width - sub_y;
|
|
}
|
|
else
|
|
{
|
|
sub_h = y + height - sub_y;
|
|
}
|
|
|
|
if (((int32)sub_w >= (int32)(image->width - 2))&&
|
|
((int32)sub_h >= (int32)(image->height - 2)))
|
|
{
|
|
lo_DisplayImageWithoutCompositor(context, (LO_ImageStruct *)image);
|
|
}
|
|
else
|
|
{
|
|
lo_DisplaySubImageWithoutCompositor(context, (LO_ImageStruct *)image,
|
|
sub_x, sub_y, sub_w, sub_h);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayEdge(MWContext *context, LO_EdgeStruct *edge)
|
|
{
|
|
if (edge->visible != FALSE)
|
|
{
|
|
FE_DisplayEdge(context, FE_VIEW, edge);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayTable(MWContext *context, LO_TableStruct *table)
|
|
{
|
|
FE_DisplayTable(context, FE_VIEW, table);
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplaySubDoc(MWContext *context, LO_SubDocStruct *subdoc)
|
|
{
|
|
FE_DisplaySubDoc(context, FE_VIEW, subdoc);
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayCell(MWContext *context, LO_CellStruct *cell)
|
|
{
|
|
/* If this cell is empty, bail */
|
|
if (cell->cell_list == NULL && cell->cell_float_list == NULL)
|
|
return;
|
|
|
|
if (context->compositor && cell->cell_bg_layer)
|
|
CL_SetLayerHidden(cell->cell_bg_layer, PR_FALSE);
|
|
|
|
FE_DisplayCell(context, FE_VIEW, cell);
|
|
}
|
|
|
|
void
|
|
lo_DisplayLineFeed(MWContext *context,
|
|
LO_LinefeedStruct *lfeed, Bool need_bg)
|
|
{
|
|
LO_TextAttr tmp_attr;
|
|
LO_TextAttr *hold_attr;
|
|
|
|
if (lfeed->ele_attrmask & LO_ELE_SELECTED)
|
|
{
|
|
lo_CopyTextAttr(lfeed->text_attr, &tmp_attr);
|
|
tmp_attr.fg.red = lfeed->text_attr->bg.red;
|
|
tmp_attr.fg.green = lfeed->text_attr->bg.green;
|
|
tmp_attr.fg.blue = lfeed->text_attr->bg.blue;
|
|
tmp_attr.bg.red = lfeed->text_attr->fg.red;
|
|
tmp_attr.bg.green = lfeed->text_attr->fg.green;
|
|
tmp_attr.bg.blue = lfeed->text_attr->fg.blue;
|
|
hold_attr = lfeed->text_attr;
|
|
lfeed->text_attr = &tmp_attr;
|
|
FE_DisplayLineFeed(context, FE_VIEW, lfeed, (XP_Bool)need_bg);
|
|
lfeed->text_attr = hold_attr;
|
|
}
|
|
else
|
|
{
|
|
FE_DisplayLineFeed(context, FE_VIEW, lfeed, (XP_Bool)need_bg);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayHR(MWContext *context, LO_HorizRuleStruct *hrule)
|
|
{
|
|
FE_DisplayHR(context, FE_VIEW, hrule);
|
|
}
|
|
|
|
|
|
void
|
|
lo_DisplayBullet(MWContext *context, LO_BulletStruct *bullet)
|
|
{
|
|
FE_DisplayBullet(context, FE_VIEW, bullet);
|
|
}
|
|
|
|
void
|
|
lo_DisplayFormElement(MWContext *context, LO_FormElementStruct *form_element)
|
|
{
|
|
CL_Layer *layer;
|
|
|
|
if (! context->compositor) {
|
|
FE_DisplayFormElement(context, FE_VIEW, form_element);
|
|
return;
|
|
}
|
|
|
|
layer = form_element->layer;
|
|
XP_ASSERT(layer);
|
|
if (! layer) /* Paranoia */
|
|
return;
|
|
|
|
if (!(form_element->ele_attrmask & LO_ELE_DRAWN)) {
|
|
/* Move layer to new position */
|
|
CL_MoveLayer(layer,
|
|
form_element->x + form_element->x_offset +
|
|
form_element->border_horiz_space,
|
|
form_element->y + form_element->y_offset +
|
|
form_element->border_vert_space);
|
|
CL_SetLayerHidden(layer, PR_FALSE);
|
|
form_element->ele_attrmask |= LO_ELE_DRAWN;
|
|
}
|
|
}
|
|
|
|
void
|
|
lo_DisplayElement(MWContext *context, LO_Element *tptr,
|
|
int32 base_x, int32 base_y,
|
|
int32 x, int32 y,
|
|
uint32 width, uint32 height)
|
|
{
|
|
LO_Any *any = &tptr->lo_any;
|
|
XP_Rect bbox;
|
|
|
|
lo_GetElementBbox(tptr, &bbox);
|
|
XP_OffsetRect(&bbox, base_x, base_y);
|
|
|
|
if (bbox.top >= (int32)(y + height))
|
|
return;
|
|
|
|
if (bbox.bottom <= y )
|
|
return;
|
|
|
|
if (bbox.left >= (int32)(x + width))
|
|
return;
|
|
|
|
if (bbox.right <= x )
|
|
return;
|
|
|
|
/* Temporarily translate to new coordinate system */
|
|
any->x += base_x;
|
|
any->y += base_y;
|
|
|
|
switch (tptr->type)
|
|
{
|
|
case LO_TEXT:
|
|
if (tptr->lo_text.text != NULL)
|
|
lo_DisplayText(context, (LO_TextStruct *)tptr, FALSE);
|
|
break;
|
|
|
|
case LO_LINEFEED:
|
|
lo_DisplayLineFeed(context, (LO_LinefeedStruct *)tptr, FALSE);
|
|
break;
|
|
|
|
case LO_HRULE:
|
|
lo_DisplayHR(context, (LO_HorizRuleStruct *)tptr);
|
|
break;
|
|
|
|
case LO_FORM_ELE:
|
|
lo_DisplayFormElement(context, (LO_FormElementStruct *)tptr);
|
|
break;
|
|
|
|
case LO_BULLET:
|
|
lo_DisplayBullet(context, (LO_BulletStruct *)tptr);
|
|
break;
|
|
|
|
case LO_IMAGE:
|
|
if (context->compositor) {
|
|
/* Allow the compositor to start drawing the image. */
|
|
lo_DisplayImage(context, (LO_ImageStruct *)tptr);
|
|
}
|
|
else {
|
|
/* There is no compositor, so draw the image directly, with the
|
|
appropriate clip. */
|
|
lo_ClipImage(context,
|
|
(LO_ImageStruct *)tptr,
|
|
(x + base_x),
|
|
(y + base_y), width, height);
|
|
}
|
|
break;
|
|
|
|
case LO_TABLE:
|
|
lo_DisplayTable(context, (LO_TableStruct *)tptr);
|
|
break;
|
|
|
|
case LO_EMBED:
|
|
lo_DisplayEmbed(context, (LO_EmbedStruct *)tptr);
|
|
break;
|
|
|
|
case LO_BUILTIN:
|
|
lo_DisplayBuiltin(context, (LO_BuiltinStruct *)tptr);
|
|
break;
|
|
|
|
#ifdef JAVA
|
|
case LO_JAVA:
|
|
lo_DisplayJavaApp(context, (LO_JavaAppStruct *)tptr);
|
|
break;
|
|
#endif
|
|
|
|
case LO_EDGE:
|
|
lo_DisplayEdge(context, (LO_EdgeStruct *)tptr);
|
|
break;
|
|
|
|
case LO_CELL:
|
|
/* If this cell is a container for an inflow layer (and
|
|
therefore not a table cell), don't descend into the cell
|
|
because the layer's painter function will handle its
|
|
display. */
|
|
if (((LO_CellStruct*)tptr)->cell_inflow_layer)
|
|
break;
|
|
|
|
/* cmanske: Order changed - display cell contents FIRST
|
|
* so selection feedback near cell border is not wiped out
|
|
* TODO: This doesn't work for images, which are display
|
|
* asynchronously. Need to add "observer" to image display
|
|
*/
|
|
lo_DisplayCellContents(context, (LO_CellStruct *)tptr,
|
|
base_x, base_y, x, y, width, height);
|
|
lo_DisplayCell(context, (LO_CellStruct *)tptr);
|
|
break;
|
|
|
|
case LO_SUBDOC:
|
|
{
|
|
LO_SubDocStruct *subdoc;
|
|
int32 new_x, new_y;
|
|
uint32 new_width, new_height;
|
|
lo_DocState *sub_state;
|
|
|
|
subdoc = (LO_SubDocStruct *)tptr;
|
|
sub_state = (lo_DocState *)subdoc->state;
|
|
|
|
if (sub_state == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lo_DisplaySubDoc(context, subdoc);
|
|
|
|
new_x = subdoc->x;
|
|
new_y = subdoc->y;
|
|
new_width = subdoc->x_offset + subdoc->width;
|
|
new_height = subdoc->y_offset + subdoc->height;
|
|
|
|
new_x = new_x - subdoc->x;
|
|
new_y = new_y - subdoc->y;
|
|
sub_state->base_x = subdoc->x +
|
|
subdoc->x_offset + subdoc->border_width;
|
|
sub_state->base_y = subdoc->y +
|
|
subdoc->y_offset + subdoc->border_width;
|
|
lo_RefreshDocumentArea(context, sub_state,
|
|
new_x, new_y, new_width, new_height);
|
|
}
|
|
break;
|
|
|
|
case LO_PARAGRAPH:
|
|
case LO_CENTER:
|
|
case LO_MULTICOLUMN:
|
|
case LO_LIST:
|
|
case LO_DESCTITLE:
|
|
case LO_DESCTEXT:
|
|
case LO_BLOCKQUOTE:
|
|
case LO_HEADING:
|
|
case LO_SPAN:
|
|
/* all non-display, doc-state mutating elements. */
|
|
break;
|
|
case LO_TEXTBLOCK:
|
|
break;
|
|
case LO_FLOAT:
|
|
case LO_LAYER:
|
|
case LO_SPACER:
|
|
break;
|
|
default:
|
|
XP_TRACE(("lo_DisplayElement(%p) skip element type = %d\n", tptr, tptr->type));
|
|
break;
|
|
}
|
|
|
|
/* Restore original element's coordinates */
|
|
any->x -= base_x;
|
|
any->y -= base_y;
|
|
}
|
|
|
|
#ifdef PROFILE
|
|
#pragma profile off
|
|
#endif
|
|
|