home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / BookmarkView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  52.9 KB  |  2,062 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    BookmarkView.h -- view of user's bookmark's.
  20.    Created: Chris Toshok <toshok@netscape.com>, 9-Aug-96.
  21.  */
  22.  
  23.  
  24.  
  25. #include "MozillaApp.h"
  26. #include "BookmarkView.h"
  27.  
  28. #if defined(USE_MOTIF_DND)
  29.  
  30. #include "OutlinerDrop.h"
  31.  
  32. #endif /* USE_MOTIF_DND */
  33.  
  34. #include "BrowserFrame.h"  // for fe_reuseBrowser
  35. #include "BookmarkFindDialog.h"
  36. #include "BookmarkWhatsNewDialog.h"
  37. #include "ViewGlue.h"
  38. #include "xfe.h"
  39. #include "xfe2_extern.h"
  40. #include "bkmks.h"
  41. #include "felocale.h" /* for fe_ConvertToLocalEncoding */
  42. #include "xp_mem.h"
  43. #include "prefapi.h"
  44.  
  45. #include "PersonalToolbar.h"
  46.  
  47. #include <Xfe/Xfe.h>
  48.  
  49. #include "xpgetstr.h"
  50. extern int XFE_BM_OUTLINER_COLUMN_NAME;
  51. extern int XFE_BM_OUTLINER_COLUMN_LOCATION;
  52. extern int XFE_BM_OUTLINER_COLUMN_LASTVISITED;
  53. extern int XFE_BM_OUTLINER_COLUMN_CREATEDON;
  54.  
  55. #define BOOKMARK_OUTLINER_GEOMETRY_PREF "bookmarks.outliner_geometry"
  56. #define READ_BUFFER_SIZE 2048
  57.  
  58. #if defined(DEBUG_toshok)||defined(DEBUG_tao)
  59. #define D(x) printf x
  60. #else
  61. #define D(x)
  62. #endif
  63.  
  64. const int XFE_BookmarkView::OUTLINER_COLUMN_NAME = 0;
  65. const int XFE_BookmarkView::OUTLINER_COLUMN_LOCATION = 1;
  66. const int XFE_BookmarkView::OUTLINER_COLUMN_LASTVISITED = 2;
  67. const int XFE_BookmarkView::OUTLINER_COLUMN_CREATEDON = 3;
  68.  
  69. /* pixmaps for use in the bookmark window. */
  70. fe_icon XFE_BookmarkView::bookmark = { 0 };
  71. fe_icon XFE_BookmarkView::mailBookmark = { 0 };
  72. fe_icon XFE_BookmarkView::newsBookmark = { 0 };
  73. fe_icon XFE_BookmarkView::changedBookmark = { 0 };
  74. fe_icon XFE_BookmarkView::closedFolder = { 0 };
  75. fe_icon XFE_BookmarkView::openedFolder = { 0 };
  76. fe_icon XFE_BookmarkView::closedPersonalFolder = { 0 };
  77. fe_icon XFE_BookmarkView::openedPersonalFolder = { 0 };
  78. fe_icon XFE_BookmarkView::closedFolderDest = { 0 };
  79. fe_icon XFE_BookmarkView::openedFolderDest = { 0 };
  80. fe_icon XFE_BookmarkView::closedFolderMenu = { 0 };
  81. fe_icon XFE_BookmarkView::openedFolderMenu = { 0 };
  82. fe_icon XFE_BookmarkView::closedFolderMenuDest = { 0 };
  83. fe_icon XFE_BookmarkView::openedFolderMenuDest = { 0 };
  84.  
  85. MenuSpec XFE_BookmarkView::open_popup_spec[] = {
  86.   { xfeCmdOpenLinkNew, PUSHBUTTON },
  87.   { xfeCmdOpenLinkEdit, PUSHBUTTON },
  88.   MENU_SEPARATOR,
  89.   { NULL },
  90. };
  91. MenuSpec XFE_BookmarkView::new_popup_spec[] = {
  92.   { xfeCmdNewBookmark, PUSHBUTTON },
  93.   { xfeCmdNewFolder, PUSHBUTTON },
  94.   { xfeCmdNewSeparator, PUSHBUTTON },
  95.   MENU_SEPARATOR,
  96.   { NULL },
  97. };
  98. MenuSpec XFE_BookmarkView::set_popup_spec[] = {
  99.   { xfeCmdSetToolbarFolder, PUSHBUTTON },
  100.   { xfeCmdSetNewBookmarkFolder, PUSHBUTTON },
  101.   { xfeCmdSetBookmarkMenuFolder, PUSHBUTTON },
  102.   MENU_SEPARATOR,
  103.   { NULL },
  104. };
  105. MenuSpec XFE_BookmarkView::saveas_popup_spec[] = {
  106.   { xfeCmdSaveLink, PUSHBUTTON },
  107.   MENU_SEPARATOR,
  108.   { NULL },
  109. };
  110. MenuSpec XFE_BookmarkView::cutcopy_popup_spec[] = {
  111.   { xfeCmdCut, PUSHBUTTON },
  112.   { xfeCmdCopy, PUSHBUTTON },
  113.   { NULL },
  114. };
  115. MenuSpec XFE_BookmarkView::copylink_popup_spec[] = {
  116.   { xfeCmdCopyLink, PUSHBUTTON },
  117.   { NULL },
  118. };
  119. MenuSpec XFE_BookmarkView::paste_popup_spec[] = {
  120.   { xfeCmdPaste, PUSHBUTTON },
  121.   { NULL },
  122. };
  123. MenuSpec XFE_BookmarkView::delete_popup_spec[] = {
  124.   { xfeCmdDelete, PUSHBUTTON },
  125.   { NULL },
  126. };
  127. MenuSpec XFE_BookmarkView::makealias_popup_spec[] = {
  128.   { xfeCmdMakeAlias, PUSHBUTTON },
  129.   { NULL },
  130. };
  131. MenuSpec XFE_BookmarkView::properties_popup_spec[] = {
  132.   MENU_SEPARATOR,
  133.   { xfeCmdBookmarkProperties, PUSHBUTTON },
  134.   { NULL },
  135. };
  136.  
  137. XFE_BookmarkView::XFE_BookmarkView(XFE_Component *toplevel_component, 
  138.                    Widget parent,
  139.                    XFE_View *parent_view, MWContext *context) 
  140.   : XFE_View(toplevel_component, parent_view, context)
  141. {
  142.   int num_columns = 4;
  143.   static int column_widths[] = {40, 40, 15, 30};
  144.  
  145.   m_propertiesDialog = NULL;
  146.   m_whatsNewDialog = NULL;
  147.   m_popup = NULL;
  148.   m_batchDepth = 0;
  149.   m_menuIsInvalid = FALSE;
  150.  
  151.   m_outliner = new XFE_Outliner("bookmarkList",
  152.                                 this, 
  153.                                 getToplevel(),
  154.                                 parent,
  155.                                 False, // constantSize 
  156.                                 True,  // hasHeadings
  157.                                 num_columns,  // Number of columns.
  158.                                 num_columns,  // Number of visible columns.
  159.                                 column_widths, 
  160.                                 BOOKMARK_OUTLINER_GEOMETRY_PREF);
  161.  
  162.   m_outliner->setHideColumnsAllowed( TRUE );
  163.   m_outliner->setPipeColumn( OUTLINER_COLUMN_NAME );
  164.   m_outliner->setMultiSelectAllowed(True);
  165.  
  166.   m_sortDescending = True;
  167.   m_lastSort = xfeCmdSortByTitle;
  168.  
  169.   m_outliner->setSortColumn( OUTLINER_COLUMN_NAME, 
  170.                              OUTLINER_SortAscending );
  171.  
  172.   setBaseWidget(m_outliner->getBaseWidget());
  173.  
  174.   // Initialize clip stuff.
  175.   clip.block = NULL;
  176.   clip.length = 0;
  177.  
  178.   {
  179.     Pixel bg_pixel;
  180.     
  181.     XtVaGetValues(m_widget, XmNbackground, &bg_pixel, 0);
  182.  
  183.     if (!bookmark.pixmap)
  184.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  185.              BlackPixelOfScreen(XtScreen(m_widget)),
  186.              bg_pixel,
  187.              &bookmark,
  188.              NULL,
  189.              BM_Bookmark.width, BM_Bookmark.height,
  190.              BM_Bookmark.mono_bits, BM_Bookmark.color_bits, BM_Bookmark.mask_bits, FALSE);
  191.  
  192.     if (!mailBookmark.pixmap)
  193.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  194.                      BlackPixelOfScreen(XtScreen(m_widget)),
  195.                      bg_pixel,
  196.                      &mailBookmark,
  197.                      NULL,
  198.                      BM_MailBookmark.width, BM_MailBookmark.height,
  199.                      BM_MailBookmark.mono_bits, BM_MailBookmark.color_bits,
  200.                      BM_MailBookmark.mask_bits, FALSE);
  201.  
  202.     if (!newsBookmark.pixmap)
  203.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  204.                      BlackPixelOfScreen(XtScreen(m_widget)),
  205.                      bg_pixel,
  206.                      &newsBookmark,
  207.                      NULL,
  208.                      BM_NewsBookmark.width, BM_NewsBookmark.height,
  209.                      BM_NewsBookmark.mono_bits, BM_NewsBookmark.color_bits,
  210.                      BM_NewsBookmark.mask_bits, FALSE);
  211.  
  212.     if (!changedBookmark.pixmap)
  213.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  214.                      BlackPixelOfScreen(XtScreen(m_widget)),
  215.                      bg_pixel,
  216.                      &changedBookmark,
  217.                      NULL,
  218.                      BM_Change.width, BM_Change.height,
  219.                      BM_Change.mono_bits, BM_Change.color_bits,
  220.                      BM_Change.mask_bits, FALSE);
  221.  
  222.     if (!closedFolder.pixmap)
  223.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  224.              BlackPixelOfScreen(XtScreen(m_widget)),
  225.              bg_pixel,
  226.              &closedFolder,
  227.              NULL,
  228.              BM_Folder.width, BM_Folder.height,
  229.              BM_Folder.mono_bits, BM_Folder.color_bits, BM_Folder.mask_bits, FALSE);
  230.  
  231.     if (!openedFolder.pixmap)
  232.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  233.              BlackPixelOfScreen(XtScreen(m_widget)),
  234.              bg_pixel,
  235.              &openedFolder,
  236.              NULL,
  237.              BM_FolderO.width, BM_FolderO.height,
  238.              BM_FolderO.mono_bits, BM_FolderO.color_bits, BM_FolderO.mask_bits, FALSE);
  239.  
  240.     if (!closedPersonalFolder.pixmap)
  241.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  242.              BlackPixelOfScreen(XtScreen(m_widget)),
  243.              bg_pixel,
  244.              &closedPersonalFolder,
  245.              NULL,
  246.              BM_PersonalFolder.width, BM_PersonalFolder.height,
  247.              BM_PersonalFolder.mono_bits, BM_PersonalFolder.color_bits, BM_PersonalFolder.mask_bits, FALSE);
  248.  
  249.     if (!openedPersonalFolder.pixmap)
  250.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  251.              BlackPixelOfScreen(XtScreen(m_widget)),
  252.              bg_pixel,
  253.              &openedPersonalFolder,
  254.              NULL,
  255.              BM_PersonalFolderO.width, BM_PersonalFolderO.height,
  256.              BM_PersonalFolderO.mono_bits, BM_PersonalFolderO.color_bits, BM_PersonalFolderO.mask_bits, FALSE);
  257.  
  258.  
  259.     if (!openedFolderDest.pixmap)
  260.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  261.              BlackPixelOfScreen(XtScreen(m_widget)),
  262.              bg_pixel,
  263.              &openedFolderDest,
  264.              NULL,
  265.              BM_NewFolderO.width, BM_NewFolderO.height,
  266.              BM_NewFolderO.mono_bits, BM_NewFolderO.color_bits, BM_NewFolderO.mask_bits, FALSE);
  267.  
  268.     if (!closedFolderDest.pixmap)
  269.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  270.              BlackPixelOfScreen(XtScreen(m_widget)),
  271.              bg_pixel,
  272.              &closedFolderDest,
  273.              NULL,
  274.              BM_NewFolder.width, BM_NewFolder.height,
  275.              BM_NewFolder.mono_bits, BM_NewFolder.color_bits, BM_NewFolder.mask_bits, FALSE);
  276.  
  277.     if (!openedFolderMenu.pixmap)
  278.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  279.              BlackPixelOfScreen(XtScreen(m_widget)),
  280.              bg_pixel,
  281.              &openedFolderMenu,
  282.              NULL,
  283.              BM_MenuFolderO.width, BM_MenuFolderO.height,
  284.              BM_MenuFolderO.mono_bits, BM_MenuFolderO.color_bits, BM_MenuFolderO.mask_bits, FALSE);
  285.  
  286.     if (!closedFolderMenu.pixmap)
  287.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  288.              BlackPixelOfScreen(XtScreen(m_widget)),
  289.              bg_pixel,
  290.              &closedFolderMenu,
  291.              NULL,
  292.              BM_MenuFolder.width, BM_MenuFolder.height,
  293.              BM_MenuFolder.mono_bits, BM_MenuFolder.color_bits, BM_MenuFolder.mask_bits, FALSE);
  294.  
  295.     if (!openedFolderMenuDest.pixmap)
  296.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  297.              BlackPixelOfScreen(XtScreen(m_widget)),
  298.              bg_pixel,
  299.              &openedFolderMenuDest,
  300.              NULL,
  301.              BM_NewAndMenuFolderO.width, BM_NewAndMenuFolderO.height,
  302.              BM_NewAndMenuFolderO.mono_bits, BM_NewAndMenuFolderO.color_bits, BM_NewAndMenuFolderO.mask_bits, FALSE);
  303.  
  304.     if (!closedFolderMenuDest.pixmap)
  305.       fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  306.              BlackPixelOfScreen(XtScreen(m_widget)),
  307.              bg_pixel,
  308.              &closedFolderMenuDest,
  309.              NULL,
  310.              BM_NewAndMenuFolder.width, BM_NewAndMenuFolder.height,
  311.              BM_NewAndMenuFolder.mono_bits, BM_NewAndMenuFolder.color_bits, BM_NewAndMenuFolder.mask_bits, FALSE);
  312.   }
  313.  
  314.  
  315. #if defined(USE_MOTIF_DND)
  316.  
  317.   m_outliner->enableDragDrop(this,
  318.                              XFE_BookmarkView::getDropTargets,
  319.                              XFE_BookmarkView::getDragTargets,
  320.                              XFE_BookmarkView::getDragIconData,
  321.                              XFE_BookmarkView::dragConvert,
  322.                              XFE_BookmarkView::processTargets);
  323. #else
  324.   m_outliner->setDragType(FE_DND_BOOKMARK, &bookmark,
  325.                           this);
  326.   fe_dnd_CreateDrop(m_outliner->getBaseWidget(), drop_func, this);
  327. #endif  /* USE_MOTIF_DND */
  328.  
  329.   // Save vertical scroller for keyboard accelerators
  330.   CONTEXT_DATA(context)->vscroll = m_outliner->getScroller();
  331.  
  332.   // jump start the bookmarkview's display
  333.   BM_InitializeBookmarksContext(context);
  334.  
  335.   BM_SetFEData(context, this);
  336.  
  337.   loadBookmarks(NULL);
  338.  
  339.   m_ancestorInfo = NULL;
  340.  
  341.   // Select the first row
  342.   if (m_outliner->getTotalLines() > 0)
  343.     {
  344.       BM_SelectItem(m_contextData, 
  345.                     BM_AtIndex(m_contextData, 1),
  346.                     TRUE, FALSE, TRUE);
  347.     }
  348.  
  349.   // Set visible rows here.  Should check to see if pref geometry is in effect.
  350.   // m_outliner->showAllRowsWithRange(10, 40);
  351. }
  352.  
  353. XFE_BookmarkView::~XFE_BookmarkView()
  354. {
  355.   if (m_propertiesDialog != NULL)
  356.     {
  357.       delete m_propertiesDialog;
  358.     }
  359.   if (m_whatsNewDialog != NULL)
  360.     {
  361.       delete m_whatsNewDialog;
  362.     }
  363. }
  364.  
  365. Boolean
  366. XFE_BookmarkView::isCommandEnabled(CommandType cmd, void *calldata,
  367.                                    XFE_CommandInfo* info)
  368. {
  369. #define IS_CMD(command) cmd == (command)
  370.   const int *selected;
  371.   int count;
  372.   
  373.   BM_CommandType bm_cmd = commandToBMCmd(cmd);
  374.  
  375.   m_outliner->getSelection(&selected, &count);
  376.   
  377.   if (IS_CMD(xfeCmdOpenSelected))
  378.     {
  379.       return count == 1 && BM_FindCommandStatus(m_contextData, bm_cmd);
  380.     } 
  381.   else if (IS_CMD(xfeCmdBookmarkProperties))
  382.     {
  383.       return count == 1 && m_propertiesDialog == 0 && 
  384.         BM_FindCommandStatus(m_contextData, bm_cmd);
  385.     }
  386.   else if (IS_CMD(xfeCmdAddToToolbar))
  387.     {
  388.       return count == 1;
  389.     } 
  390.   else if (IS_CMD(xfeCmdMoveBookmarkUp))
  391.     {
  392.       return count == 1 && selected[0] > 1;
  393.     } 
  394.   else if (IS_CMD(xfeCmdMoveBookmarkDown))
  395.     {
  396.       return count == 1 && selected[0] != 0
  397.         && selected[0] < m_outliner->getTotalLines() - 1;
  398.     } 
  399.   else if (IS_CMD(xfeCmdBookmarksWhatsNew))
  400.     {
  401.       return m_whatsNewDialog == 0;
  402.     }
  403.   else if (IS_CMD(xfeCmdSortAscending) 
  404.            || IS_CMD(xfeCmdSortDescending))
  405.     {
  406.       return m_lastSort != xfeCmdSortByTitle;
  407.     }
  408.   else if (IS_CMD(xfeCmdSortByTitle)
  409.            || IS_CMD(xfeCmdSortByLocation)
  410.            || IS_CMD(xfeCmdSortByDateLastVisited)
  411.            || IS_CMD(xfeCmdSortByDateCreated)
  412.            )
  413.     {
  414.       return TRUE;
  415.     }
  416.   else if (IS_CMD(xfeCmdOpenLinkNew)
  417.            || IS_CMD(xfeCmdOpenLinkEdit)
  418.            || IS_CMD(xfeCmdSaveLink)
  419.            || IS_CMD(xfeCmdCopyLink)
  420.            )
  421.     {
  422.       return count == 1;
  423.     }
  424.   else if (bm_cmd != BM_Cmd_Invalid)
  425.     {
  426.       return BM_FindCommandStatus(m_contextData, bm_cmd);
  427.     }
  428.   else
  429.     {
  430.       return XFE_View::isCommandEnabled(cmd, calldata, info);
  431.     }
  432. #undef IS_CMD
  433. }
  434.  
  435. BM_CommandType
  436. XFE_BookmarkView::commandToBMCmd(CommandType cmd)
  437. {
  438.     // mcafee: what is this?   (BM_CommandType)~0;
  439.     BM_CommandType bm_cmd = BM_Cmd_Invalid;  
  440.     
  441. #define BEGIN_BM_MAP() if (0) ;
  442. #define BM_CMDMAP(the_cmd, the_bm_cmd) else if (cmd == (the_cmd)) bm_cmd = (the_bm_cmd);
  443.     
  444.     // Map bookmark commands onto xfeCmd's.
  445.     // By default, these commands will just be shoved into
  446.     // BM_ObeyCommand() in XFE_BookmarkView::doCommand().
  447.     // Commands that need special attention will be intercepted
  448.     // and called directly.
  449.     BEGIN_BM_MAP()
  450.     
  451.     BM_CMDMAP(xfeCmdNewBookmark, BM_Cmd_InsertBookmark) // New Bookmark...
  452.     BM_CMDMAP(xfeCmdNewFolder,          BM_Cmd_InsertHeader)   // New Folder...
  453.     BM_CMDMAP(xfeCmdNewSeparator,       BM_Cmd_InsertSeparator)// New Separator
  454.     BM_CMDMAP(xfeCmdOpenSelected,       BM_Cmd_GotoBookmark)   // Open Selected
  455.     BM_CMDMAP(xfeCmdOpenBookmarkFile,   BM_Cmd_Open)           // Open Bookmark File...
  456.     BM_CMDMAP(xfeCmdImport, BM_Cmd_ImportBookmarks) // Import...
  457.     BM_CMDMAP(xfeCmdSaveAs, BM_Cmd_SaveAs)          // Save As...
  458.     BM_CMDMAP(xfeCmdMakeAlias, BM_Cmd_MakeAlias)       // Make Alias
  459.     BM_CMDMAP(xfeCmdClose,  BM_Cmd_Close)           // Close
  460.  
  461.     BM_CMDMAP(xfeCmdUndo,  BM_Cmd_Undo)
  462.     BM_CMDMAP(xfeCmdRedo,  BM_Cmd_Redo)
  463.     BM_CMDMAP(xfeCmdCut,   BM_Cmd_Cut)
  464.     BM_CMDMAP(xfeCmdCopy,  BM_Cmd_Copy)
  465.     BM_CMDMAP(xfeCmdPaste, BM_Cmd_Paste)
  466.     BM_CMDMAP(xfeCmdDelete,             BM_Cmd_Delete)
  467.     BM_CMDMAP(xfeCmdSelectAll,          BM_Cmd_SelectAllBookmarks)
  468.     BM_CMDMAP(xfeCmdFindInObject,       BM_Cmd_Find)
  469.     BM_CMDMAP(xfeCmdFindAgain,          BM_Cmd_FindAgain)
  470.     BM_CMDMAP(xfeCmdBookmarkProperties, BM_Cmd_BookmarkProps)
  471.     
  472.     BM_CMDMAP(xfeCmdSortByTitle,             BM_Cmd_Sort_Natural)
  473.     BM_CMDMAP(xfeCmdSortByLocation,         (m_sortDescending
  474.                                              ? BM_Cmd_Sort_Address
  475.                                              : BM_Cmd_Sort_Address_Asc))
  476.     BM_CMDMAP(xfeCmdSortByDateLastVisited,  (m_sortDescending
  477.                                              ? BM_Cmd_Sort_LastVisit
  478.                                              : BM_Cmd_Sort_LastVisit_Asc))
  479.     BM_CMDMAP(xfeCmdSortByDateCreated,      (m_sortDescending
  480.                                              ? BM_Cmd_Sort_AddDate
  481.                                              : BM_Cmd_Sort_AddDate_Asc))
  482.   
  483.     BM_CMDMAP(xfeCmdSortBookmarks,      BM_Cmd_SortBookmarks) // Sort Bookmarks
  484.     BM_CMDMAP(xfeCmdSetNewBookmarkFolder, BM_Cmd_SetAddHeader)
  485.     BM_CMDMAP(xfeCmdSetBookmarkMenuFolder,  BM_Cmd_SetMenuHeader)
  486.     BM_CMDMAP(xfeCmdSetToolbarFolder,  BM_Cmd_SetMenuHeader)
  487.  
  488.     return bm_cmd;
  489.     
  490. #undef BEGIN_BM_MAP
  491. #undef BM_CMDMAP
  492. }
  493.  
  494. void
  495. XFE_BookmarkView::doCommand(CommandType cmd, void *calldata, XFE_CommandInfo*info)
  496. {
  497.   const int *    selected;
  498.   int            count;
  499.   
  500.   m_outliner->getSelection(&selected, &count);
  501.         
  502.   if (cmd == xfeCmdSortAscending 
  503.       || cmd == xfeCmdSortDescending)
  504.     {
  505.       m_sortDescending = !m_sortDescending;
  506.       
  507.       cmd = m_lastSort;
  508.     }
  509.   
  510.   BM_CommandType bm_cmd = commandToBMCmd(cmd);
  511.     
  512.   if (cmd == xfeCmdOpenSelected)
  513.     {
  514.       if (count == 1)
  515.         {
  516.           BM_Entry* entry = BM_AtIndex(m_contextData, selected[0] + 1);
  517.           
  518.           if (entry) {
  519.             BM_GotoBookmark(m_contextData, entry);
  520.           }
  521.         }
  522.     }
  523.   else if (cmd == xfeCmdSetToolbarFolder)
  524.     {
  525.       if (count == 1)
  526.         {
  527.           BM_Entry * entry = BM_AtIndex(m_contextData,selected[0] + 1);
  528.           
  529.           if (entry && BM_IsHeader(entry))
  530.             {
  531.               XFE_PersonalToolbar::setToolbarFolder(entry,True);
  532.               refreshCells();
  533.             }
  534.         }
  535.     }
  536.   else if (cmd == xfeCmdMoveBookmarkUp)
  537.     {
  538.       if (count == 1 && selected[0] > 0)
  539.         {
  540.           startBatch();
  541.           BM_DoDrop(m_contextData, selected[0] - 1, True);
  542.           endBatch();
  543.  
  544.           m_outliner->makeVisible(selected[0]);
  545.         }
  546.     }
  547.   else if (cmd == xfeCmdMoveBookmarkDown)
  548.     {
  549.       if (count == 1 && selected[0] != 0
  550.           && selected[0] < m_outliner->getTotalLines() - 1)
  551.         {
  552.           BM_Entry *entry = BM_AtIndex(m_contextData, selected[0] + 1);
  553.  
  554.  
  555.           startBatch();
  556.  
  557.           // Close a folder when moving it down in the list
  558.           if (entry && BM_IsHeader(entry) && !BM_IsFolded(entry))
  559.             {
  560.               BM_FoldHeader(m_contextData, entry, TRUE, FALSE, FALSE);
  561.             }
  562.  
  563.           BM_DoDrop(m_contextData, selected[0] + 2, True);
  564.           endBatch();
  565.  
  566.           m_outliner->makeVisible(selected[0]);
  567.         }
  568.     }
  569.   else if (cmd == xfeCmdBookmarksWhatsNew)
  570.     {
  571.       startWhatsChanged();
  572.     }
  573.   else if (cmd == xfeCmdAddToToolbar)
  574.     {
  575.       if (count == 1 && selected[0] >= 0
  576.           && selected[0] < m_outliner->getTotalLines() - 1)
  577.         {
  578.           BM_Entry * personalTB =
  579.             XFE_PersonalToolbar::getToolbarFolder();
  580.           BM_Entry *entry = 
  581.             BM_AtIndex(m_contextData, selected[0] + 1);
  582.           
  583.           if (personalTB && entry)
  584.             {
  585.               BM_Entry* new_entry = 
  586.                 BM_CopyBookmark(m_contextData, entry);
  587.               
  588.               BM_AppendToHeader(m_contextData, personalTB, new_entry);
  589.             }
  590.         }
  591.     }
  592.   else if (cmd == xfeCmdShowPopup)
  593.     {
  594.       doPopup(info->event);
  595.     }
  596.   else if (cmd == xfeCmdOpenLinkNew)
  597.     {
  598.       if (count == 1)
  599.         {
  600.           BM_Entry* entry = BM_AtIndex(m_contextData, selected[0] + 1);
  601.           char *url = BM_GetAddress(entry);
  602.  
  603.           if (url) 
  604.             {
  605.               fe_showBrowser(XfeAncestorFindApplicationShell(CONTEXT_WIDGET (m_contextData)),
  606.                              NULL, NULL, 
  607.                              NET_CreateURLStruct (url, NET_DONT_RELOAD));
  608.             }
  609.         }
  610.     }
  611. #ifdef EDITOR
  612.   else if (cmd == xfeCmdOpenLinkEdit)
  613.     {
  614.       if (count == 1)
  615.         {
  616.           BM_Entry* entry = BM_AtIndex(m_contextData, selected[0] + 1);
  617.           char *url = BM_GetAddress(entry);
  618.  
  619.           if (url) 
  620.             {
  621. #ifdef MOZ_MAIL_NEWS
  622.               if (MSG_RequiresComposeWindow(url))
  623.                 fe_reuseBrowser(m_contextData,
  624.                                 NET_CreateURLStruct(url, NET_DONT_RELOAD));
  625.               else
  626. #endif
  627.                 fe_EditorNew(m_contextData, (XFE_Frame *)m_toplevel,
  628.                              NULL, url);
  629.             }
  630.         }
  631.     }
  632. #endif  // EDITOR
  633.   else if (cmd == xfeCmdSaveLink)
  634.     {
  635.       if (count == 1)
  636.         {
  637.           BM_Entry* entry = BM_AtIndex(m_contextData, selected[0] + 1);
  638.           char *url = BM_GetAddress(entry);
  639.  
  640.           if (url) 
  641.             {
  642.               fe_SaveURL(m_contextData,
  643.                          NET_CreateURLStruct (url, NET_DONT_RELOAD));
  644.             }
  645.         }
  646.     }
  647.   else if (cmd == xfeCmdCopyLink)
  648.     {
  649.       if (count == 1)
  650.         {
  651.           BM_Entry* entry = BM_AtIndex(m_contextData, selected[0] + 1);
  652.           char *url = BM_GetAddress(entry);
  653.  
  654.           if (url) 
  655.             {
  656.               fe_clipboard_link_cb (CONTEXT_WIDGET (m_contextData),
  657.                                     (XtPointer) m_contextData, NULL,
  658.                                     NET_CreateURLStruct (url, NET_DONT_RELOAD));
  659.             }
  660.         }
  661.     }
  662.   else if (cmd == xfeCmdSortByTitle
  663.            || cmd == xfeCmdSortByLocation
  664.            || cmd == xfeCmdSortByDateLastVisited
  665.            || cmd == xfeCmdSortByDateCreated
  666.            )
  667.     {
  668.       EOutlinerSortDirection sortDir = (m_sortDescending ?
  669.                                         OUTLINER_SortAscending :
  670.                                         OUTLINER_SortDescending );
  671.  
  672.       if (cmd == xfeCmdSortByTitle)
  673.         {
  674.           if (m_lastSort == xfeCmdSortByTitle) {
  675.             XBell (XtDisplay(m_widget), 0);
  676.             return;
  677.           }
  678.           m_outliner->setSortColumn(OUTLINER_COLUMN_NAME, sortDir);
  679.         }
  680.       else if (cmd == xfeCmdSortByLocation)
  681.         m_outliner->setSortColumn(OUTLINER_COLUMN_LOCATION, sortDir);
  682.       else if (cmd == xfeCmdSortByDateLastVisited)
  683.         m_outliner->setSortColumn(OUTLINER_COLUMN_LASTVISITED, sortDir);
  684.       else if (cmd == xfeCmdSortByDateCreated)
  685.         m_outliner->setSortColumn(OUTLINER_COLUMN_CREATEDON, sortDir);
  686.       
  687.       m_lastSort = cmd;
  688.           
  689.       BM_SelectAll( m_contextData, FALSE );
  690.  
  691.       startBatch();
  692.       BM_ObeyCommand(m_contextData, bm_cmd);
  693.       endBatch();
  694.  
  695.       BM_ClearAllSelection( m_contextData, TRUE );
  696.  
  697.       // Select first item
  698.       BM_SelectItem(m_contextData, 
  699.                     BM_AtIndex(m_contextData, 1),
  700.                     TRUE, FALSE, TRUE);
  701.     }
  702.   else if (bm_cmd != BM_Cmd_Invalid)
  703.     {
  704.       startBatch();
  705.       BM_ObeyCommand(m_contextData, bm_cmd);
  706.       endBatch();
  707.     }
  708.   else
  709.     {
  710.       XFE_View::doCommand(cmd,calldata,info);
  711.     }
  712. }
  713.  
  714. Boolean
  715. XFE_BookmarkView::handlesCommand(CommandType cmd, void *calldata,
  716.                                  XFE_CommandInfo* info)
  717. {
  718. #define IS_CMD(command) cmd == (command)
  719.  
  720.   if (IS_CMD(xfeCmdOpenSelected)
  721.       || IS_CMD(xfeCmdNewBookmark)
  722.       || IS_CMD(xfeCmdNewFolder)
  723.       || IS_CMD(xfeCmdNewSeparator)
  724.       || IS_CMD(xfeCmdOpenSelected)
  725.       || IS_CMD(xfeCmdOpenBookmarkFile)
  726.       || IS_CMD(xfeCmdImport)
  727.       || IS_CMD(xfeCmdSaveAs)
  728.       || IS_CMD(xfeCmdAddToToolbar)
  729.       || IS_CMD(xfeCmdMakeAlias)
  730.       || IS_CMD(xfeCmdClose)
  731.  
  732.       || IS_CMD(xfeCmdUndo)
  733.       || IS_CMD(xfeCmdRedo)
  734.       || IS_CMD(xfeCmdCut)
  735.       || IS_CMD(xfeCmdCopy)
  736.       || IS_CMD(xfeCmdPaste)
  737.       || IS_CMD(xfeCmdDelete)
  738.       || IS_CMD(xfeCmdSelectAll)
  739.       || IS_CMD(xfeCmdFindInObject)
  740.       || IS_CMD(xfeCmdFindAgain)
  741.       || IS_CMD(xfeCmdBookmarkProperties)
  742.  
  743.       || IS_CMD(xfeCmdMoveBookmarkUp)
  744.       || IS_CMD(xfeCmdMoveBookmarkDown)
  745.       || IS_CMD(xfeCmdSetNewBookmarkFolder)
  746.       || IS_CMD(xfeCmdSetBookmarkMenuFolder)
  747.       || IS_CMD(xfeCmdSetToolbarFolder)
  748.  
  749.       || IS_CMD(xfeCmdSortBookmarks)
  750.       || IS_CMD(xfeCmdSortByTitle)
  751.       || IS_CMD(xfeCmdSortByLocation)
  752.       || IS_CMD(xfeCmdSortByDateLastVisited)
  753.       || IS_CMD(xfeCmdSortByDateCreated)
  754.       || IS_CMD(xfeCmdSortAscending)
  755.       || IS_CMD(xfeCmdSortDescending)
  756.  
  757.       || IS_CMD(xfeCmdBookmarksWhatsNew)
  758.  
  759.       // Popup commands
  760.       || IS_CMD(xfeCmdShowPopup)
  761.       || IS_CMD(xfeCmdOpenLinkNew)
  762.       || IS_CMD(xfeCmdOpenLinkEdit)
  763.       || IS_CMD(xfeCmdSaveLink)
  764.       || IS_CMD(xfeCmdCopyLink)
  765.     )
  766.     {
  767.       return True;
  768.     }
  769.   else
  770.     {
  771.       return XFE_View::handlesCommand(cmd, calldata, info);
  772.     }
  773. #undef IS_CMD
  774. }
  775.  
  776. XP_Bool
  777. XFE_BookmarkView::isCommandSelected(CommandType cmd,
  778.                                     void *calldata, XFE_CommandInfo* info)
  779. {
  780. #define IS_CMD(command) cmd == (command)
  781.  
  782.   // This method is designed for toggle button.
  783.   // We want to keep the toggle button to have the same state
  784.   //   as its matched view.
  785.  
  786.   if (IS_CMD(xfeCmdSortByTitle)
  787.       || IS_CMD(xfeCmdSortByLocation)
  788.       || IS_CMD(xfeCmdSortByDateLastVisited)
  789.       || IS_CMD(xfeCmdSortByDateCreated)
  790.       )
  791.     {
  792.       return m_lastSort == cmd;
  793.     }
  794.   else if (IS_CMD(xfeCmdSortAscending))
  795.     {
  796.       return !m_sortDescending;
  797.     }
  798.   else if (IS_CMD(xfeCmdSortDescending))
  799.     {
  800.       return m_sortDescending;
  801.     }
  802.   else
  803.     {
  804.       XFE_View *view = getParent();
  805.       return (view && view->isCommandSelected(cmd, calldata, info));
  806.     }
  807.  
  808. #undef IS_CMD
  809. }
  810.  
  811. char *
  812. XFE_BookmarkView::commandToString(CommandType, void*, XFE_CommandInfo*)
  813. {
  814.     return NULL;
  815. }
  816.  
  817.  
  818. Boolean
  819. XFE_BookmarkView::loadBookmarks(char *filename)
  820. {
  821.   char url[512];
  822.   XP_StatStruct st;
  823.   int result;
  824.  
  825.   if (!filename)
  826.     filename = fe_globalPrefs.bookmark_file;
  827.  
  828.   result = XP_Stat( filename, &st, xpBookmarks);
  829.  
  830.   if (result == -1 && errno == ENOENT 
  831.       && filename && *filename) {
  832.     // Since the bookmarks file does not exist,
  833.     //   try to copy the default one.
  834.     char *defaultBM = fe_getDefaultBookmarks();
  835.     
  836.     if (defaultBM) {
  837.       copyBookmarksFile(filename, defaultBM);
  838.       XP_FREE(defaultBM);
  839.     }
  840.   }
  841.   PR_snprintf(url, sizeof(url), "file:%s", filename);
  842.   
  843.   BM_ReadBookmarksFromDisk(m_contextData, filename, url);
  844.  
  845.   return True;
  846. }
  847.  
  848. Boolean
  849. XFE_BookmarkView::copyBookmarksFile(char *dst, char *src)
  850. {
  851.   XP_File src_fp, dst_fp;
  852.   char buffer[READ_BUFFER_SIZE];
  853.  
  854.   src_fp = XP_FileOpen(src, xpBookmarks, XP_FILE_READ);
  855.   if (!src_fp) return False;
  856.  
  857.   dst_fp = XP_FileOpen(dst, xpBookmarks, XP_FILE_WRITE);
  858.   if (!dst_fp) return False;
  859.  
  860.   Boolean writeOk = True;
  861.   int length = 0;
  862.   while (XP_FileReadLine(buffer, READ_BUFFER_SIZE, src_fp) && writeOk) {
  863.     length = XP_STRLEN(buffer);
  864.     if (XP_FileWrite(buffer, length, dst_fp) < length) {
  865.       writeOk = False;
  866.     }
  867.   }
  868.   XP_FileClose(src_fp);
  869.   XP_FileClose(dst_fp);
  870.  
  871.   return writeOk;
  872. }
  873.  
  874. // Methods from the outlinable interface.
  875. void *
  876. XFE_BookmarkView::ConvFromIndex(int /*index*/)
  877. {
  878.   XP_ASSERT(0);
  879.   return 0;
  880. }
  881.  
  882. int
  883. XFE_BookmarkView::ConvToIndex(void */*item*/)
  884. {
  885.   XP_ASSERT(0);
  886.   return 0;
  887. }
  888.  
  889.  
  890. void *
  891. XFE_BookmarkView::acquireLineData(int line)
  892. {
  893.   BM_Entry *tmp;
  894.  
  895.   m_entryDepth = 0;
  896.  
  897.   m_entry = BM_AtIndex(m_contextData, line + 1);
  898.  
  899.   if (!m_entry)
  900.     return NULL;
  901.  
  902.   tmp = m_entry;
  903.   
  904.   while ( (tmp = BM_GetParent(tmp) ) != NULL )
  905.       m_entryDepth ++;
  906.  
  907.   m_ancestorInfo = new OutlinerAncestorInfo[ m_entryDepth + 1];
  908.   
  909.   if (m_entryDepth)
  910.       {
  911.           BM_Entry *tmp;
  912.           int i;
  913.           
  914.           for (tmp = m_entry, i = m_entryDepth;
  915.                tmp != NULL;
  916.                tmp = BM_GetParent(tmp), i --)
  917.               {
  918.                   m_ancestorInfo[i].has_next = BM_HasNext(tmp);
  919.                   m_ancestorInfo[i].has_prev = BM_HasPrev(tmp);
  920.               }
  921.       }
  922.   else
  923.       {
  924.           m_ancestorInfo[0].has_next = BM_HasNext (m_entry);
  925.           m_ancestorInfo[0].has_prev = BM_HasPrev (m_entry);
  926.       }
  927.   
  928.   return m_entry;
  929. }
  930.  
  931. void
  932. XFE_BookmarkView::getTreeInfo(XP_Bool *expandable,
  933.                   XP_Bool *is_expanded,
  934.                   int *depth,
  935.                   OutlinerAncestorInfo **ancestor)
  936. {
  937.   XP_Bool is_entry_expandable = False;
  938.   XP_Bool is_entry_expanded = False;
  939.  
  940.   XP_ASSERT(m_entry);
  941.  
  942.   if (!m_entry)
  943.   {
  944.       return;
  945.   }
  946.  
  947.   is_entry_expandable = BM_IsHeader(m_entry) && BM_GetChildren(m_entry);
  948.   if (is_entry_expandable)
  949.     is_entry_expanded = ! BM_IsFolded(m_entry);
  950.  
  951.   if (expandable)
  952.     *expandable = is_entry_expandable;
  953.  
  954.   if (is_expanded)
  955.     *is_expanded = is_entry_expanded;
  956.  
  957.   if (depth)
  958.     *depth = m_entryDepth;
  959.  
  960.   if (ancestor)
  961.     *ancestor = m_ancestorInfo;
  962. }
  963.  
  964. EOutlinerTextStyle
  965. XFE_BookmarkView::getColumnStyle(int /*column*/)
  966. {
  967.   XP_ASSERT(m_entry);
  968.  
  969.   return BM_IsAlias(m_entry) ? OUTLINER_Italic : OUTLINER_Default;
  970. }
  971.  
  972. char *
  973. XFE_BookmarkView::getColumnText(int column)
  974. {
  975.   static char *separator_string = "--------------------";
  976.   static char name_buf[1024];
  977.   static char location_buf[1024];
  978.   static char visited_buf[1024];
  979.   static char added_buf[1024];
  980.  
  981.   XP_ASSERT(m_entry);
  982.  
  983.   switch (column)
  984.     {
  985.     case OUTLINER_COLUMN_NAME:
  986.       if (BM_IsSeparator(m_entry))
  987.     return separator_string;
  988.       else
  989.     {
  990.       char *name;
  991.       unsigned char *loc;
  992.       
  993.       name = BM_GetName(m_entry);
  994.       loc = fe_ConvertToLocaleEncoding(INTL_DefaultWinCharSetID(NULL), (unsigned char*)name);
  995.       
  996.       XP_STRNCPY_SAFE(name_buf, (const char *)loc, sizeof(name_buf));
  997.       
  998.       if ((char *) loc != name)
  999.         {
  1000.           XP_FREE(loc);
  1001.         }
  1002.       
  1003.       return name_buf;
  1004.     }
  1005.     case OUTLINER_COLUMN_LOCATION:
  1006.       {
  1007.     char *address = BM_GetAddress(m_entry);
  1008.     
  1009.     if (address && !BM_IsHeader(m_entry))
  1010.       {
  1011.         XP_STRNCPY_SAFE(location_buf, address, sizeof(location_buf));
  1012.       
  1013.         return location_buf;
  1014.       }
  1015.     else
  1016.       {
  1017.         return "---";
  1018.       }
  1019.       }
  1020.     case OUTLINER_COLUMN_LASTVISITED:
  1021.       {
  1022.     char *visited = BM_PrettyLastVisitedDate(m_entry);
  1023.     
  1024.     if (visited)
  1025.       {
  1026.         XP_STRNCPY_SAFE(visited_buf, visited, sizeof(visited_buf));
  1027.  
  1028.         return visited_buf;
  1029.       }
  1030.     else
  1031.       {
  1032.         return "---";
  1033.       }
  1034.       }    
  1035.     case OUTLINER_COLUMN_CREATEDON:
  1036.       {
  1037.         char *added = BM_PrettyAddedOnDate(m_entry);
  1038.  
  1039.         if (added)
  1040.       {
  1041.         XP_STRNCPY_SAFE(added_buf, added, sizeof(added_buf));
  1042.       
  1043.         return added_buf;
  1044.       }
  1045.     else
  1046.       {
  1047.         return "-";
  1048.       }
  1049.       }
  1050.     default:
  1051.       XP_ASSERT(0);
  1052.       return NULL;
  1053.     }
  1054. }
  1055.  
  1056. fe_icon *
  1057. XFE_BookmarkView::getColumnIcon(int column)
  1058. {
  1059.     XP_ASSERT(m_entry);
  1060.  
  1061.     if (column != OUTLINER_COLUMN_NAME)
  1062.         return NULL;
  1063.     
  1064.     /* do the icon for this bookmark */
  1065.     if (m_entry && (m_entry == XFE_PersonalToolbar::getToolbarFolder()))
  1066.         {
  1067.             if (BM_IsFolded(m_entry))
  1068.                 {
  1069.                     return &closedPersonalFolder;
  1070.                 }
  1071.             else
  1072.                 {
  1073.                     return &openedPersonalFolder;
  1074.                 }
  1075.         }
  1076.     else if (BM_IsHeader(m_entry)) 
  1077.         {
  1078.             static fe_icon *icon_list[] = {
  1079.                 &openedFolder,
  1080.                 &closedFolder,
  1081.                 &openedFolderDest,
  1082.                 &closedFolderDest,
  1083.                 &openedFolderMenu,
  1084.                 &closedFolderMenu,
  1085.                 &openedFolderMenuDest,
  1086.                 &closedFolderMenuDest
  1087.             };
  1088.             int key = 0;
  1089.             
  1090.             if (BM_IsFolded(m_entry)) key++;
  1091.             if (m_entry == BM_GetAddHeader(m_contextData)) key += 2;
  1092.             if (m_entry == BM_GetMenuHeader(m_contextData)) key += 4;
  1093.             return icon_list[key];
  1094.         } 
  1095.     else 
  1096.         {
  1097.             if (BM_IsAlias(m_entry) && BM_IsHeader(BM_GetAliasOriginal(m_entry))) 
  1098.                 {
  1099.                     return &closedFolder;
  1100.                 } 
  1101.             else 
  1102.                 {
  1103.                     int url_type = NET_URL_Type(BM_GetAddress(m_entry));
  1104.  
  1105.                     switch (url_type)
  1106.                         {
  1107.                         case IMAP_TYPE_URL:
  1108.                         case MAILBOX_TYPE_URL:
  1109.                             return &mailBookmark;
  1110.                         case NEWS_TYPE_URL:
  1111.                             return &newsBookmark;
  1112.                         default:
  1113.                           {
  1114.                             if( BM_GetChangedState(m_entry) == BM_CHANGED_YES )
  1115.                               return &changedBookmark;
  1116.                             else
  1117.                               return &bookmark;
  1118.                           }
  1119.                         }
  1120.                 }
  1121.         }
  1122. }
  1123.  
  1124. char *
  1125. XFE_BookmarkView::getColumnName(int column)
  1126. {
  1127.     switch (column)
  1128.         {
  1129.         case OUTLINER_COLUMN_NAME:
  1130.             return "Name";
  1131.         case OUTLINER_COLUMN_LOCATION:
  1132.             return "Location";
  1133.         case OUTLINER_COLUMN_LASTVISITED:
  1134.             return "LastVisited";
  1135.         case OUTLINER_COLUMN_CREATEDON:
  1136.             return "CreatedOn";
  1137.         default:
  1138.             XP_ASSERT(0);
  1139.             return 0;
  1140.         }
  1141. }
  1142.  
  1143. char *
  1144. XFE_BookmarkView::getColumnHeaderText(int column)
  1145. {
  1146.     switch (column)
  1147.         {
  1148.         case OUTLINER_COLUMN_NAME:
  1149.             return XP_GetString(XFE_BM_OUTLINER_COLUMN_NAME);
  1150.         case OUTLINER_COLUMN_LOCATION:
  1151.             return XP_GetString(XFE_BM_OUTLINER_COLUMN_LOCATION);
  1152.         case OUTLINER_COLUMN_LASTVISITED:
  1153.             return XP_GetString(XFE_BM_OUTLINER_COLUMN_LASTVISITED);
  1154.         case OUTLINER_COLUMN_CREATEDON:
  1155.             return XP_GetString(XFE_BM_OUTLINER_COLUMN_CREATEDON);
  1156.         default:
  1157.             XP_ASSERT(0);
  1158.             return 0;
  1159.         }
  1160. }
  1161.  
  1162. fe_icon *
  1163. XFE_BookmarkView::getColumnHeaderIcon(int /*column*/)
  1164. {
  1165.   return 0;
  1166. }
  1167.  
  1168. EOutlinerTextStyle
  1169. XFE_BookmarkView::getColumnHeaderStyle(int /*column*/)
  1170. {
  1171.   return OUTLINER_Default;
  1172. }
  1173.  
  1174. void
  1175. XFE_BookmarkView::releaseLineData()
  1176. {
  1177.   delete [] m_ancestorInfo;
  1178.   m_ancestorInfo = NULL;
  1179. }
  1180.  
  1181. void
  1182. XFE_BookmarkView::Buttonfunc(const OutlineButtonFuncData *data)
  1183. {
  1184.   if (data->row == -1) 
  1185.     {
  1186.       CommandType sortCmd = m_lastSort;
  1187.  
  1188.       switch(data->column)
  1189.         {
  1190.         case OUTLINER_COLUMN_NAME:
  1191.           sortCmd = xfeCmdSortByTitle;
  1192.           break;
  1193.         case OUTLINER_COLUMN_LOCATION:
  1194.           sortCmd = xfeCmdSortByLocation;
  1195.           break;
  1196.         case OUTLINER_COLUMN_LASTVISITED:
  1197.           sortCmd = xfeCmdSortByDateLastVisited;
  1198.           break;
  1199.         case OUTLINER_COLUMN_CREATEDON:
  1200.           sortCmd = xfeCmdSortByDateCreated;
  1201.           break;
  1202.         default:
  1203.           sortCmd = 0;
  1204.         }
  1205.       if (sortCmd && isCommandEnabled(sortCmd))
  1206.           {
  1207.             if (sortCmd == m_lastSort && sortCmd != xfeCmdSortByTitle)
  1208.               m_sortDescending = !m_sortDescending;
  1209.             else
  1210.               m_sortDescending = True;
  1211.  
  1212.             xfe_ExecuteCommand((XFE_Frame *)m_toplevel, sortCmd);
  1213.           }
  1214.       return;
  1215.     }
  1216.  
  1217.   BM_Entry* entry = BM_AtIndex(m_contextData, data->row + 1);
  1218.  
  1219.   if (!entry) return;
  1220.  
  1221.   if (data->clicks == 1)
  1222.     {
  1223.       if (data->ctrl) 
  1224.         {
  1225.           m_outliner->toggleSelected(data->row);
  1226.           
  1227.           BM_ToggleItem(m_contextData, entry, TRUE, TRUE);
  1228.         } 
  1229.       else if (data->shift) 
  1230.         {
  1231.           // select the range.
  1232.           const int *selected;
  1233.           int count;
  1234.       
  1235.           m_outliner->getSelection(&selected, &count);
  1236.       
  1237.           if (count == 0) 
  1238.             {
  1239.               // there wasn't anything selected yet.
  1240.               BM_SelectItem(m_contextData, entry, TRUE, FALSE, TRUE);
  1241.             }
  1242.           else if (count == 1)
  1243.             {
  1244.               // There was only one, so we select the range from
  1245.               //    that item to the new one.
  1246.               BM_SelectRangeTo(m_contextData, entry);
  1247.             }
  1248.           else
  1249.             {
  1250.               // we had a range of items selected, so let's do
  1251.               // something really nice with them.
  1252.               BM_SelectRangeTo(m_contextData, entry);
  1253.             }
  1254.         } 
  1255.       else 
  1256.         {
  1257.           BM_SelectItem(m_contextData, entry, TRUE, FALSE, TRUE);
  1258.  
  1259.           if (data->button == Button2) 
  1260.             {
  1261.               xfe_ExecuteCommand((XFE_Frame *)m_toplevel, 
  1262.                                  xfeCmdOpenLinkNew);
  1263.             }
  1264.         }
  1265.     }
  1266.   else if (data->clicks == 2) 
  1267.     {
  1268.       BM_SelectItem(m_contextData, entry, TRUE, FALSE, TRUE);
  1269.       
  1270.       if (BM_IsAlias(entry) || BM_IsUrl(entry)) 
  1271.         {
  1272.           BM_GotoBookmark(m_contextData, entry);
  1273.         }
  1274.       else if (BM_IsHeader(entry))
  1275.         {
  1276.           if (!BM_IsFolded(entry))
  1277.             {
  1278.               BM_ClearAllChildSelection(m_contextData, entry, TRUE);
  1279.             }
  1280.           
  1281.           BM_FoldHeader(m_contextData, entry, !BM_IsFolded(entry), TRUE, FALSE);
  1282.         }
  1283.     }
  1284.   
  1285.   getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1286. }
  1287.  
  1288. void
  1289. XFE_BookmarkView::Flippyfunc(const OutlineFlippyFuncData *data)
  1290. {
  1291.     BM_Entry *entry = BM_AtIndex(m_contextData, data->row + 1);
  1292.     if (entry && BM_IsHeader(entry))
  1293.         {
  1294.             if (!BM_IsFolded(entry))
  1295.                 {
  1296.                     BM_ClearAllChildSelection(m_contextData, entry, TRUE);
  1297.                 }
  1298.             
  1299.             BM_FoldHeader(m_contextData, entry, !BM_IsFolded(entry), TRUE, FALSE);
  1300.         }
  1301. }
  1302.  
  1303. XFE_Outliner *
  1304. XFE_BookmarkView::getOutliner()
  1305. {
  1306.   return m_outliner;
  1307. }
  1308.  
  1309. void
  1310. XFE_BookmarkView::refreshCells(int first, int last, XP_Bool /*now*/)
  1311. {
  1312.     int i;
  1313.     
  1314.     if (last == BM_LAST_CELL)
  1315.         last = BM_GetVisibleCount(m_contextData);
  1316.  
  1317.     m_outliner->change(first - 1, last - first + 1,
  1318.                        BM_GetVisibleCount(m_contextData));
  1319.     
  1320.     for (i = first-1; i < last; i ++)
  1321.         {
  1322.             BM_Entry *entry = BM_AtIndex(m_contextData, i + 1);
  1323.             XP_Bool bm_selected = BM_IsSelected(entry);
  1324.             XP_Bool outliner_selected = m_outliner->isSelected(i);
  1325.  
  1326.             if (bm_selected && !outliner_selected)
  1327.                 m_outliner->selectItem(i);
  1328.             else if (!bm_selected && outliner_selected)
  1329.                 m_outliner->deselectItem(i);
  1330.         }
  1331.     
  1332.   //    fe_OutlineSetMaxDepth(BM_DATA(bm_context)->outline,
  1333.   //              BM_GetMaxDepth(bm_context));
  1334. }
  1335.  
  1336. void
  1337. XFE_BookmarkView::gotoBookmark(const char *url)
  1338. {
  1339.     // Goto the bookmark reusing a browser (or possibly creating a new one)
  1340.     MWContext * context = 
  1341.       fe_reuseBrowser(m_contextData,NET_CreateURLStruct(url, NET_DONT_RELOAD));
  1342.  
  1343.     // If everything looks good, popup the browser in case its lost in space
  1344.     if (context && (context->type == MWContextBrowser))
  1345.     {
  1346.         XFE_BrowserFrame * frame = (XFE_BrowserFrame *)
  1347.             ViewGlue_getFrame(XP_GetNonGridContext(context));
  1348.         
  1349.         if (frame && frame->isAlive())
  1350.         {
  1351.             Widget w = frame->getBaseWidget();
  1352.  
  1353.             XMapRaised(XtDisplay(w),XtWindow(w));
  1354.  
  1355.             XtPopup(w,XtGrabNone);
  1356.         }
  1357.     }
  1358. }
  1359.  
  1360. void
  1361. XFE_BookmarkView::scrollIntoView(BM_Entry *entry)
  1362. {
  1363.   int num = BM_GetIndex(m_contextData, entry);
  1364.  
  1365.   if (num > 0) 
  1366.       m_outliner->makeVisible(num - 1);
  1367. }
  1368.  
  1369. void
  1370. XFE_BookmarkView::setClipContents(void *block, int32 length)
  1371. {
  1372.   freeClipContents();
  1373.   
  1374.   clip.block = XP_ALLOC(length);
  1375.   XP_MEMCPY(clip.block, block, length);
  1376.   clip.length = length;
  1377. }
  1378.  
  1379. void *
  1380. XFE_BookmarkView::getClipContents(int32 *length)
  1381. {
  1382.   if (length)
  1383.     *length = clip.length;
  1384.  
  1385.   return (clip.block);
  1386. }
  1387.  
  1388. void
  1389. XFE_BookmarkView::freeClipContents()
  1390. {
  1391.   if (clip.block) XP_FREE(clip.block);
  1392.  
  1393.   clip.block = NULL;
  1394.   clip.length = 0;
  1395. }
  1396.  
  1397. void
  1398. XFE_BookmarkView::openBookmarksWindow()
  1399. {
  1400.   if (m_propertiesDialog == NULL)
  1401.     {
  1402.       m_propertiesDialog =
  1403.         new XFE_BookmarkPropDialog(m_contextData, getToplevel()->getBaseWidget());
  1404.       
  1405.       XtAddCallback(m_propertiesDialog->getBaseWidget(),
  1406.                     XmNdestroyCallback, properties_destroy_cb, this);
  1407.     }
  1408.  
  1409.   m_propertiesDialog->show();
  1410.  
  1411.   getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1412. }
  1413.  
  1414. void
  1415. XFE_BookmarkView::closeBookmarksWindow()
  1416. {
  1417.   if (m_propertiesDialog)
  1418.     {
  1419.       m_propertiesDialog->close();
  1420.       m_propertiesDialog = 0;
  1421.     }
  1422.  
  1423.   getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1424. }
  1425.  
  1426. void
  1427. XFE_BookmarkView::startWhatsChanged()
  1428. {
  1429.   if (m_whatsNewDialog == NULL)
  1430.     {
  1431.       m_whatsNewDialog =
  1432.         new XFE_BookmarkWhatsNewDialog(m_contextData, getToplevel()->getBaseWidget());
  1433.       
  1434.       XtAddCallback(m_whatsNewDialog->getBaseWidget(),
  1435.                     XmNdestroyCallback, whats_new_destroy_cb, this);
  1436.     }
  1437.  
  1438.   m_whatsNewDialog->show();
  1439.  
  1440.   getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  1441. }
  1442.  
  1443. void
  1444. XFE_BookmarkView::updateWhatsChanged(const char *url, int32 done, int32 total,
  1445.                                      const char *totaltime)
  1446. {
  1447.   m_whatsNewDialog->updateWhatsChanged(url, done, total, totaltime);
  1448. }
  1449.  
  1450. void
  1451. XFE_BookmarkView::finishedWhatsChanged(int32 totalchecked, int32 numreached, int32 numchanged)
  1452. {
  1453.   m_whatsNewDialog->finishedWhatsChanged(totalchecked, numreached, numchanged);
  1454. }
  1455.  
  1456. /* The dialog is deleted on destroy */
  1457. void 
  1458. XFE_BookmarkView::properties_destroy_cb(Widget /* widget */, XtPointer closure,
  1459.                                         XtPointer /* call_data */)
  1460. {
  1461.   XFE_BookmarkView* obj = (XFE_BookmarkView *)closure;
  1462.  
  1463.   obj->m_propertiesDialog = NULL;
  1464. }
  1465.  
  1466. /* The dialog is deleted on destroy */
  1467. void 
  1468. XFE_BookmarkView::whats_new_destroy_cb(Widget /* widget */, XtPointer closure,
  1469.                                         XtPointer /* call_data */)
  1470. {
  1471.   XFE_BookmarkView* obj = (XFE_BookmarkView *)closure;
  1472.  
  1473.   obj->m_whatsNewDialog = NULL;
  1474. }
  1475.  
  1476. void
  1477. XFE_BookmarkView::editItem(BM_Entry *entry)
  1478. {
  1479.   if (m_propertiesDialog && entry)
  1480.     {
  1481.       m_propertiesDialog->editItem(entry);
  1482.     }
  1483. }
  1484.  
  1485. void
  1486. XFE_BookmarkView::entryGoingAway(BM_Entry *entry)
  1487. {
  1488.   if (m_propertiesDialog != NULL &&
  1489.       m_propertiesDialog->isShown())
  1490.     {
  1491.       m_propertiesDialog->entryGoingAway(entry);
  1492.     }
  1493. }
  1494.  
  1495. void 
  1496. XFE_BookmarkView::setName(BM_Entry *entry, char *name)
  1497. {
  1498.   char * toolbarName = XFE_PersonalToolbar::getToolbarFolderName();
  1499.   XP_Bool isPersonalToolbar = FALSE;
  1500.  
  1501.   startBatch();
  1502.  
  1503.   if (toolbarName && XP_STRCMP(toolbarName,BM_GetName(entry)) == 0) {
  1504.     isPersonalToolbar = TRUE;
  1505.   }
  1506.  
  1507.   BM_SetName(m_contextData, entry, name);
  1508.  
  1509.   if (isPersonalToolbar) {
  1510.     XFE_PersonalToolbar::setToolbarFolder(entry, FALSE);  
  1511.   }
  1512.   
  1513.   endBatch();
  1514. }
  1515.  
  1516. void
  1517. XFE_BookmarkView::bookmarkMenuInvalid()
  1518. {
  1519.   if (m_batchDepth == 0)
  1520.     {
  1521.       XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::bookmarksHaveChanged);
  1522.  
  1523.       BMFE_RefreshCells(m_contextData, 1, BM_LAST_CELL, TRUE);
  1524.       
  1525.       m_menuIsInvalid = FALSE;
  1526.     }
  1527.   else
  1528.     {
  1529.       // Since we are in a BE call, delay the update
  1530.       // until after the call is finished
  1531.       m_menuIsInvalid = TRUE;
  1532.     }
  1533. }
  1534.  
  1535. extern "C" void
  1536. BMFE_BookmarkMenuInvalid (MWContext* bm_context)
  1537. {
  1538.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1539.  
  1540.   if (view)
  1541.     view->bookmarkMenuInvalid();
  1542. }
  1543.  
  1544. extern "C" void
  1545. BMFE_UpdateWhatsChanged(MWContext* bm_context, const char* url,
  1546.                         int32 done, int32 total,
  1547.                         const char* totaltime)
  1548. {
  1549.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1550.  
  1551.   if (view)
  1552.     view->updateWhatsChanged(url, done, total, totaltime);
  1553. }
  1554.  
  1555. extern "C" void 
  1556. BMFE_FinishedWhatsChanged(MWContext* bm_context, int32 totalchecked,
  1557.                           int32 numreached, int32 numchanged)
  1558. {
  1559.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1560.  
  1561.   if (view)
  1562.     view->finishedWhatsChanged(totalchecked, numreached, numchanged);
  1563. }
  1564.  
  1565. void
  1566. BMFE_RefreshCells(MWContext* bm_context, int32 first, int32 last,
  1567.           XP_Bool now )
  1568. {
  1569.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1570.  
  1571.   // Need this if because this call might (and does) happen before
  1572.   // we've call BM_SetFEData on the bookmark context.
  1573.   if (view)
  1574.     view->refreshCells(first, last, now);
  1575. }
  1576.  
  1577. void
  1578. BMFE_SyncDisplay(MWContext* bm_context)
  1579. {
  1580.   BMFE_RefreshCells(bm_context, 1, BM_LAST_CELL, TRUE);
  1581. }
  1582.  
  1583. void
  1584. BMFE_MeasureEntry(MWContext* /*bm_context*/, BM_Entry* /*entry*/,
  1585.           uint32* width, uint32* height )
  1586. {
  1587.   *width = 1;            /* ### */
  1588.   *height = 1;
  1589. }
  1590.  
  1591. void
  1592. BMFE_FreeClipContents(MWContext* bm_context)
  1593. {
  1594.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1595.   
  1596.   if (view)
  1597.     view->freeClipContents();
  1598. }
  1599.  
  1600. void *
  1601. BMFE_GetClipContents(MWContext* bm_context, int32* length)
  1602. {
  1603.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1604.  
  1605.   if (view)
  1606.     return view->getClipContents(length);
  1607.   else
  1608.     return NULL;
  1609. }
  1610.  
  1611. void
  1612. BMFE_SetClipContents(MWContext* bm_context, void *block, int32 length )
  1613. {
  1614.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1615.  
  1616.   if (view)
  1617.     view->setClipContents(block, length);
  1618. }
  1619.  
  1620. void
  1621. BMFE_OpenBookmarksWindow(MWContext* bm_context)
  1622. {
  1623.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1624.  
  1625.   if (view)
  1626.     view->openBookmarksWindow();
  1627. }
  1628.  
  1629. void
  1630. BMFE_EditItem(MWContext* bm_context, BM_Entry* entry )
  1631. {
  1632.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1633.   
  1634.   if (view)
  1635.     view->editItem(entry);
  1636. }
  1637.  
  1638. void
  1639. BMFE_EntryGoingAway(MWContext* bm_context, BM_Entry* entry)
  1640. {
  1641.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1642.  
  1643.   if (view)
  1644.     view->entryGoingAway(entry);
  1645.  
  1646. #if 0
  1647.   if (entry)
  1648.   {
  1649.       char * name = XFE_PersonalToolbar::getToolbarFolderName();
  1650.       
  1651.       if (name && XP_STRCMP(name,BM_GetName(entry)))
  1652.       {
  1653.           XFE_PersonalToolbar::setToolbarFolder(NULL,True);  
  1654.       }
  1655.   }
  1656. #endif
  1657. }
  1658.  
  1659.  
  1660. void
  1661. BMFE_CloseBookmarksWindow(MWContext* bm_context )
  1662. {
  1663.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1664.  
  1665.   if (view)
  1666.     view->closeBookmarksWindow();
  1667. }
  1668.  
  1669.  
  1670. void
  1671. BMFE_GotoBookmark(MWContext* bm_context, const char* url, const char * /* target */ )
  1672. {
  1673.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1674.  
  1675.   if (view)
  1676.     view->gotoBookmark(url);
  1677. }
  1678.  
  1679.  
  1680. void*
  1681. BMFE_OpenFindWindow(MWContext* bm_context, BM_FindInfo* findInfo )
  1682. {
  1683.     XFE_Frame *frame = ViewGlue_getFrame(bm_context);
  1684.  
  1685.     fe_showBMFindDialog(frame->getBaseWidget(),
  1686.                         findInfo);
  1687.  
  1688.     return 0;
  1689. }
  1690.  
  1691.  
  1692. void
  1693. BMFE_ScrollIntoView(MWContext* bm_context, BM_Entry* entry)
  1694. {
  1695.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1696.  
  1697.   if (view)
  1698.     view->scrollIntoView(entry);
  1699. }
  1700.  
  1701. void
  1702. BMFE_StartBatch(MWContext* bm_context)
  1703. {
  1704.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1705.  
  1706.   if (view)
  1707.     view->startBatch();
  1708. }
  1709.  
  1710. void
  1711. BMFE_EndBatch(MWContext* bm_context)
  1712. {
  1713.   XFE_BookmarkView *view = (XFE_BookmarkView*)BM_GetFEData(bm_context);
  1714.  
  1715.   if (view)
  1716.     view->endBatch();
  1717. }
  1718.  
  1719. void
  1720. XFE_BookmarkView::startBatch()
  1721. {
  1722.   m_batchDepth += 1;
  1723. }
  1724.  
  1725. void
  1726. XFE_BookmarkView::endBatch()
  1727. {
  1728.   m_batchDepth -= 1;
  1729.  
  1730.   XP_ASSERT(m_batchDepth >= 0);
  1731.  
  1732.   if (m_batchDepth == 0 && m_menuIsInvalid)
  1733.     bookmarkMenuInvalid();
  1734. }
  1735.  
  1736. #if !defined(USE_MOTIF_DND)
  1737. void
  1738. XFE_BookmarkView::dropfunc(Widget /*dropw*/, fe_dnd_Event type,
  1739.                            fe_dnd_Source *source, XEvent *event)
  1740. {
  1741.     int row = -1;
  1742.     int x, y;
  1743.  
  1744.     /* we only understand these targets -- well, we only understand
  1745.        the first two. The outliner understands the COLUMN one. */
  1746.     if (source->type != FE_DND_COLUMN &&
  1747.         source->type != FE_DND_URL &&
  1748.         source->type != FE_DND_BOOKMARK)
  1749.         {
  1750.             return;
  1751.         }
  1752.  
  1753.     if (source->type == FE_DND_COLUMN)
  1754.         {
  1755.             m_outliner->handleDragEvent(event, type, source);
  1756.  
  1757.             return;
  1758.         }
  1759.  
  1760.     m_outliner->translateFromRootCoords(event->xbutton.x_root, event->xbutton.y_root, &x, &y);
  1761.     
  1762.     XP_Bool isBelow = FALSE;
  1763.  
  1764.     row = m_outliner->XYToRow(x, y, &isBelow);
  1765.  
  1766.     switch (type)
  1767.         {
  1768.         case FE_DND_START:
  1769.             break;
  1770.         case FE_DND_DRAG:
  1771.             if (BM_IsDragEffectBox(m_contextData, row + 1, isBelow))
  1772.                 m_outliner->outlineLine(row);
  1773.             else
  1774.                 m_outliner->underlineLine(row);
  1775.             break;
  1776.         case FE_DND_DROP:
  1777.             if (row >= 0)
  1778.                 {
  1779.                     if (source->type == FE_DND_BOOKMARK)
  1780.                         {
  1781.                           startBatch();
  1782.                           BM_DoDrop(m_contextData, row + 1, isBelow);
  1783.                           endBatch();
  1784.                         }
  1785.                     else if (source->type == FE_DND_URL)
  1786.                         {
  1787.                         }
  1788.  
  1789.                     // to clear the drag feedback.
  1790.                     if (BM_IsDragEffectBox(m_contextData, row + 1, isBelow))
  1791.                         m_outliner->outlineLine(-1);
  1792.                     else
  1793.                         m_outliner->underlineLine(-1);
  1794.                 }
  1795.             break;
  1796.         case FE_DND_END:
  1797.             break;
  1798.         }
  1799. }
  1800.  
  1801. void
  1802. XFE_BookmarkView::drop_func(Widget dropw, void *closure, fe_dnd_Event type,
  1803.                             fe_dnd_Source *source, XEvent* event)
  1804. {
  1805.     XFE_BookmarkView *obj = (XFE_BookmarkView*)closure;
  1806.     
  1807.     obj->dropfunc(dropw, type, source, event);
  1808. }
  1809. #endif /* */
  1810.  
  1811. void
  1812. XFE_BookmarkView::doPopup(XEvent *event)
  1813. {
  1814.   int x, y, clickrow;
  1815.   BM_Entry *entryUnderMouse;
  1816.  
  1817.   Widget widget = XtWindowToWidget(event->xany.display, event->xany.window);
  1818.   if (widget == NULL)
  1819.     widget = m_widget;
  1820.         
  1821.   if (m_popup)
  1822.     delete m_popup;
  1823.  
  1824.   m_outliner->translateFromRootCoords(event->xbutton.x_root,
  1825.                                       event->xbutton.y_root,
  1826.                                       &x, &y);
  1827.  
  1828.   clickrow = m_outliner->XYToRow(x, y);
  1829.  
  1830.   if (clickrow > -1) 
  1831.       entryUnderMouse = BM_AtIndex(m_contextData, clickrow + 1);
  1832.   else
  1833.       entryUnderMouse = NULL;
  1834.         
  1835.  
  1836.   m_popup = new XFE_PopupMenu("popup",
  1837.                               (XFE_Frame*)m_toplevel, // XXXXXXX
  1838.                               widget,
  1839.                               NULL);
  1840.  
  1841.   XP_Bool isUrl = BM_IsUrl(entryUnderMouse) || BM_IsAlias(entryUnderMouse);
  1842.   XP_Bool isFolder = BM_IsHeader(entryUnderMouse);
  1843.   
  1844.   // possible types - url, alias, address, separator, header (i.e. folder)
  1845.  
  1846.   if (isUrl)             m_popup->addMenuSpec(open_popup_spec);
  1847.   if (1)                 m_popup->addMenuSpec(new_popup_spec);  // always add
  1848.   if (isFolder)          m_popup->addMenuSpec(set_popup_spec);
  1849.   if (isUrl)             m_popup->addMenuSpec(saveas_popup_spec);
  1850.   if (entryUnderMouse)   m_popup->addMenuSpec(cutcopy_popup_spec);
  1851.   if (isUrl)             m_popup->addMenuSpec(copylink_popup_spec);
  1852.   if (BM_FindCommandStatus(m_contextData, BM_Cmd_Paste))
  1853.                          m_popup->addMenuSpec(paste_popup_spec);
  1854.   if (entryUnderMouse)   m_popup->addMenuSpec(delete_popup_spec);
  1855.   if (isUrl)             m_popup->addMenuSpec(makealias_popup_spec);
  1856.   if (isUrl || isFolder) m_popup->addMenuSpec(properties_popup_spec);
  1857.  
  1858.   // Make sure we select what is under the mouse
  1859.   if (entryUnderMouse)
  1860.     {
  1861.       BM_SelectItem(m_contextData, entryUnderMouse,
  1862.                     TRUE, FALSE, TRUE);
  1863.     }
  1864.  
  1865.   m_popup->position(event);
  1866.   
  1867.   m_popup->show();
  1868. }
  1869.  
  1870. #if defined(USE_MOTIF_DND)
  1871. fe_icon_data *
  1872. XFE_BookmarkView::GetDragIconData(int row, int column)
  1873. {
  1874.   D(("XFE_BookmarkView::GetDragIconData()\n"));
  1875.   
  1876.   return &BM_Bookmark;
  1877. }
  1878.  
  1879. fe_icon_data *
  1880. XFE_BookmarkView::getDragIconData(void *this_ptr,
  1881.                                 int row,
  1882.                                 int column)
  1883. {
  1884.   D(("XFE_Bookmarkview::getDragIconData()\n"));
  1885.   XFE_BookmarkView *bookmark_view = (XFE_BookmarkView*)this_ptr;
  1886.  
  1887.   return bookmark_view->GetDragIconData(row, column);
  1888. }
  1889.  
  1890. void
  1891. XFE_BookmarkView::GetDragTargets(int row, int column,
  1892.                                  Atom **targets,
  1893.                                  int *num_targets)
  1894. {
  1895.   D(("XFE_FolderView::GetDragTargets()\n"));
  1896.   int depth;
  1897.   int flags;
  1898.  
  1899.   XP_ASSERT(row > -1);
  1900.   if (row == -1)
  1901.     {
  1902.       *targets = NULL;
  1903.       *num_targets = 0;
  1904.     }
  1905.   else
  1906.     {
  1907.       if (!m_outliner->isSelected(row))
  1908.         m_outliner->selectItemExclusive(row);
  1909.  
  1910.       *num_targets = 2;
  1911.  
  1912.       *targets = new Atom[ *num_targets ];
  1913.  
  1914.       (*targets)[0] = XFE_DropBase::_XA_NETSCAPE_URL;
  1915.       (*targets)[1] = XA_STRING;
  1916.     }
  1917. }
  1918.  
  1919. void
  1920. XFE_BookmarkView::getDragTargets(void *this_ptr,
  1921.                                int row,
  1922.                                int column,
  1923.                                Atom **targets,
  1924.                                int *num_targets)
  1925. {
  1926.   D(("XFE_BookmarkView::getDragTargets()\n"));
  1927.   XFE_BookmarkView *bookmark_view = (XFE_BookmarkView*)this_ptr;
  1928.  
  1929.   bookmark_view->GetDragTargets(row, column, targets, num_targets);
  1930. }
  1931.  
  1932. void 
  1933. XFE_BookmarkView::getDropTargets(void */*this_ptr*/,
  1934.                                Atom **targets,
  1935.                                int *num_targets)
  1936. {
  1937.   D(("XFE_BookmarkView::getDropTargets()\n"));
  1938.   *num_targets = 2;
  1939.   *targets = new Atom[ *num_targets ];
  1940.  
  1941.   (*targets)[0] = XFE_DragBase::_XA_NETSCAPE_URL;
  1942.   (*targets)[1] = XA_STRING;
  1943. }
  1944.  
  1945. char *
  1946. XFE_BookmarkView::DragConvert(Atom atom)
  1947. {
  1948.   if (atom == XFE_DragBase::_XA_NETSCAPE_URL)
  1949.     {
  1950.       // translate drag data to NetscapeURL format
  1951.       XFE_URLDesktopType urlData;
  1952.       char *result;
  1953.       const int *selection;
  1954.       int count;
  1955.       int i;
  1956.  
  1957.       m_outliner->getSelection(&selection, &count);
  1958.  
  1959.       urlData.createItemList(count);
  1960.  
  1961.       for (i = 0; i < count; i ++)
  1962.         {
  1963.           BM_Entry *entry = BM_AtIndex(m_contextData, selection[i] + 1);
  1964.  
  1965.           urlData.url(i,BM_GetAddress(entry));
  1966.         }
  1967.  
  1968.       result = XtNewString(urlData.getString());
  1969.       
  1970.       return result;
  1971.     }
  1972.   else if (atom == XFE_OutlinerDrop::_XA_NETSCAPE_BOOKMARK)
  1973.     {
  1974.       return (char*)XtNewString("");
  1975.     }
  1976.   else if (atom == XA_STRING)
  1977.     {
  1978. #if notyet
  1979.       return (char*)XtNewString(BM_GetAddress(m_dragentry));
  1980. #endif
  1981.     }
  1982. }
  1983.  
  1984. char *
  1985. XFE_BookmarkView::dragConvert(void *this_ptr,
  1986.                             Atom atom)
  1987. {
  1988.   XFE_BookmarkView *bookmark_view = (XFE_BookmarkView*)this_ptr;
  1989.   
  1990.   return bookmark_view->DragConvert(atom);
  1991. }
  1992.  
  1993. int
  1994. XFE_BookmarkView::ProcessTargets(int row, int col,
  1995.                                  Atom *targets,
  1996.                                  const char **data,
  1997.                                  int numItems)
  1998. {
  1999.   int i;
  2000.  
  2001.   D(("XFE_BookmarkView::ProcessTargets(row=%d, col=%d, numItems=%d)\n",row, col, numItems));
  2002.  
  2003.   for (i = 0; i<numItems; i ++)
  2004.     {
  2005.       if (targets[i]==None || data[i]==NULL || strlen(data[i])==0)
  2006.         continue;
  2007.  
  2008.       D(("  [%d] %s: \"%s\"\n",i,XmGetAtomName(XtDisplay(m_widget),targets[i]),data[i]));
  2009.  
  2010.       if (targets[i] == XFE_DropBase::_XA_NETSCAPE_URL)
  2011.         {          
  2012.           BM_Entry *drop_entry;
  2013.           XFE_URLDesktopType urlData(data[i]);
  2014.           int i;
  2015.  
  2016.           drop_entry = BM_AtIndex(m_contextData, row + 1);
  2017.           if (!drop_entry) return FALSE;
  2018.  
  2019.           for (i = urlData.numItems() - 1; i >= 0; i --)
  2020.             {
  2021.               const char *title;
  2022.               BM_Entry* new_entry;
  2023.  
  2024.               title = urlData.title(i);
  2025.               if (!title) title = urlData.url(i);
  2026.  
  2027.               new_entry = BM_NewUrl(title,
  2028.                                     urlData.url(i),
  2029.                                     NULL, 0);
  2030.  
  2031.               BM_InsertItemInHeaderOrAfterItem(m_contextData,
  2032.                                                drop_entry,
  2033.                                                new_entry);
  2034.             }
  2035.  
  2036.           return TRUE;
  2037.         }
  2038.       else if (targets[i] == XFE_OutlinerDrop::_XA_NETSCAPE_BOOKMARK)
  2039.         {
  2040.           startBatch();
  2041.           BM_DoDrop(m_contextData, row + 1, FALSE);
  2042.           endBatch();
  2043.           return TRUE;
  2044.         }
  2045.     }
  2046.  
  2047.   return FALSE;
  2048. }
  2049.  
  2050. int
  2051. XFE_BookmarkView::processTargets(void *this_ptr,
  2052.                                int row, int col,
  2053.                                Atom *targets,
  2054.                                const char **data,
  2055.                                int numItems)
  2056. {
  2057.   XFE_BookmarkView *bookmark_view = (XFE_BookmarkView*)this_ptr;
  2058.   
  2059.   return bookmark_view->ProcessTargets(row, col, targets, data, numItems);
  2060. }
  2061. #endif /* USE_MOTIF_DND */
  2062.