/* -*- 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. */ /* HTMLDrag.cpp -- class definition for the HTMLView drag class Created: Alastair Gourlay , 1-Jan-96. */ #include #include #include #include "HTMLDrag.h" #include "layers.h" #if defined(DEBUG_sgidev) || defined(DEBUG_tao) #define XDEBUG(x) x #else #define XDEBUG(x) #endif // // XFE_HTMLDrag class // static void HTMLDragDestroyCb(Widget,XtPointer,XtPointer); // provide access to HTML Drag class from old XFE C code. extern "C" void XFE_HTMLDragCreate(Widget widget,MWContext *context) { if (widget && context) { XFE_HTMLDrag *htmlDrag=new XFE_HTMLDrag(widget,context); XtAddCallback(widget,XmNdestroyCallback,HTMLDragDestroyCb,(XtPointer)htmlDrag); } } // auto-cleanup of classes created with C API static void HTMLDragDestroyCb(Widget widget,XtPointer cd, XtPointer) { XDEBUG(printf("HTMLDragDestroyCb(%x)\n",widget)); if (cd) { XFE_HTMLDrag *htmlDrag=(XFE_HTMLDrag*)cd; delete htmlDrag; } } // constructor XFE_HTMLDrag::XFE_HTMLDrag(Widget w,MWContext *context) : XFE_DragNetscape(w) { _context=context; } // destructor XFE_HTMLDrag::~XFE_HTMLDrag() { } // Called by xfe.c, in the Layer event handler when a link // is armed by a Button1Down. // (Motif DND needs a hook into the Layer event mgmt in order // to process drags on links within layers.) static CL_Layer *_dragLayer=NULL; extern "C" void fe_HTMLDragSetLayer(CL_Layer *layer) { // record layer of Button1 press on a link in a layer _dragLayer=layer; } // Extract URL from context, layer, x, y // (caller must free the returned URL_Struct) // Note: XFE_HTMLView has similar code, but FE_HTMLDrag doesn't // have an XFE_HTMLView*, only an MWContext*. URL_Struct * XFE_HTMLDrag::urlAtPosition(int x, int y, CL_Layer *layer) { URL_Struct *urlStruct = NULL; if (!_context) return NULL; // adjust for document origin int docX = x + CONTEXT_DATA(_context)->document_x; int docY = y + CONTEXT_DATA(_context)->document_y; // adjust layer origin if (layer) { docX -= CL_GetLayerXOrigin(layer); docY -= CL_GetLayerYOrigin(layer); } LO_Element *le=LO_XYToElement(_context,docX,docY,layer); if (!le) return NULL; switch (le->type) { case LO_TEXT: if (le->lo_text.anchor_href && le->lo_text.anchor_href->anchor) urlStruct = NET_CreateURLStruct ((char *)le->lo_text.anchor_href->anchor, NET_DONT_RELOAD); break; case LO_IMAGE: { long ix = le->lo_image.x + le->lo_image.x_offset; long iy = le->lo_image.y + le->lo_image.y_offset; long mx = docX - ix - le->lo_image.border_width; long my = docY - iy - le->lo_image.border_width; // check for client-side image map if (le->lo_image.image_attr->usemap_name != NULL) { LO_AnchorData *anchorData=LO_MapXYToAreaAnchor(_context, (LO_ImageStruct *)le, mx, my); if (anchorData && anchorData->anchor) urlStruct=NET_CreateURLStruct ((char *)anchorData->anchor, NET_DONT_RELOAD); } // check for regular image or server-side image map else if (le->lo_image.anchor_href && le->lo_image.anchor_href->anchor) { urlStruct=NET_CreateURLStruct ((char *)le->lo_image.anchor_href->anchor, NET_DONT_RELOAD); // if this is an image map (and not an about: link), add the //coordinates to the URL if (XP_STRNCASECMP(urlStruct->address, "about:",6)!=0 && le->lo_image.image_attr->attrmask & LO_ATTR_ISMAP) { NET_AddCoordinatesToURLStruct (urlStruct, ((mx < 0) ? 0 : mx), ((my < 0) ? 0 : my)); } } } break; default: urlStruct=NULL; break; } return urlStruct; } // // drag virtual methods - derived class can override // // decide if this drag is interesting int XFE_HTMLDrag::dragStart(int x,int y) { XDEBUG(printf("XFE_HTMLDrag::dragStart(%d,%d)\n",x,y)); _dragURLStruct=urlAtPosition(x,y,_dragLayer); // clean up drag layer for next click _dragLayer=NULL; if (!_dragURLStruct || !_dragURLStruct->address || strlen(_dragURLStruct->address)==0) return FALSE; // reject URL's which don't point to document: // addbook:add URL's // mailbox:displayattachments URL // javascript code // about: urls // mailto: urls if (XP_STRNCASECMP(_dragURLStruct->address,"addbook:add",11)==0 || XP_STRNCASECMP(_dragURLStruct->address,"about:",6)==0 || XP_STRNCASECMP(_dragURLStruct->address,"mailto:",7)==0 || XP_STRNCASECMP(_dragURLStruct->address,"mailbox:displayattachments",26)==0 || XP_STRNCASECMP(_dragURLStruct->address,"javascript:",11)==0) return FALSE; // disarm link and clear selection, since XmDragStart() will steal the Btn1Up XtCallActionProc(_widget,"DisarmLink",(XEvent*)&_dragButtonEvent,NULL,0); LO_ClearSelection(_context); // files get dragged to desktop as a symbolic link if (isFileURL(_dragURLStruct->address)) dragFilesAsLinks(TRUE); // try to be sensitive to type of URL #ifdef MOZ_MAIL_NEWS setDragIconForType(guessUrlMimeType(_dragURLStruct->address)); #endif return TRUE; } // specify types for this particular drag void XFE_HTMLDrag::targets() { _numTargets=2; _targets=new Atom[_numTargets]; _targets[0]=_XA_NETSCAPE_URL; _targets[1]=XA_STRING; setFileTarget(_XA_NETSCAPE_URL); } // specify operations for this particualr drag void XFE_HTMLDrag::operations() { _operations=XmDROP_COPY; } // provide data for requested target from targets() list char *XFE_HTMLDrag::getTargetData(Atom target) { // WARNING - data *must* be allocated with Xt malloc API, since Xt // will free the data with XtFree() if (target==_XA_NETSCAPE_URL) { // translate drag data to NetscapeURL format XFE_URLDesktopType urlData; urlData.createItemList(1); urlData.url(0,_dragURLStruct->address); return (char*)XtNewString(urlData.getString()); } if (target==XA_STRING) { // return the URL return (char*)XtNewString(_dragURLStruct->address); } return NULL; } // clean up after drag void XFE_HTMLDrag::dragComplete() { if (_dragURLStruct) { NET_FreeURLStruct(_dragURLStruct); _dragURLStruct=NULL; } }