home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / HistoryView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  29.9 KB  |  1,239 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.    HistoryView.h -- view of user's history
  20.    Created: Stephen Lamm <slamm@netscape.com>, 24-Feb-97.
  21.  */
  22.  
  23.  
  24.  
  25. #include "MozillaApp.h"
  26. #include "HistoryView.h"
  27.  
  28. #if defined(USE_MOTIF_DND)
  29. #include "OutlinerDrop.h"
  30. #endif /* USE_MOTIF_DND */
  31.  
  32. #include "BookmarkFrame.h"  // for fe_getBookmarkContext
  33. #include "BrowserFrame.h"  // for fe_reuseBrowser
  34. #include "PersonalToolbar.h" // for XFE_PersonalToolbar::getToolbarFolder
  35. #include "xfe.h"
  36. #include "bkmks.h"    // for BM_NewUrl
  37. #include "felocale.h" /* for fe_ConvertToLocalEncoding */
  38. #include "prefs.h"    // for fe_showPreferences
  39. #include "xplocale.h" // for FE_StrfTime
  40. #include "xp_mem.h"
  41. #include "prefapi.h"
  42. #include "undo.h"
  43. #include "xpgetstr.h"
  44. extern int XFE_HISTORY_OUTLINER_COLUMN_TITLE;
  45. extern int XFE_HISTORY_OUTLINER_COLUMN_LOCATION;
  46. extern int XFE_HISTORY_OUTLINER_COLUMN_FIRSTVISITED;
  47. extern int XFE_HISTORY_OUTLINER_COLUMN_LASTVISITED;
  48. extern int XFE_HISTORY_OUTLINER_COLUMN_EXPIRES;
  49. extern int XFE_HISTORY_OUTLINER_COLUMN_VISITCOUNT;
  50.  
  51. #if DEBUG_username
  52. #define DDD(x) x
  53. #else
  54. #define DDD(x)
  55. #endif
  56.  
  57. #define HISTORY_OUTLINER_GEOMETRY_PREF "history.outliner_geometry"
  58. // date format is like "19:21 Thu 27 Feb 97"
  59. //#define DATE_FORMAT "%H:%M %a %e %b %y"
  60. //
  61. // I liked my date format better, but in the name of consistency, 
  62. //   we will do this instead...
  63. #define DATE_FORMAT  XP_DATE_TIME_FORMAT
  64.  
  65. const int XFE_HistoryView::OUTLINER_COLUMN_TITLE        = 0;
  66. const int XFE_HistoryView::OUTLINER_COLUMN_LOCATION     = 1;
  67. const int XFE_HistoryView::OUTLINER_COLUMN_FIRSTVISITED = 2;
  68. const int XFE_HistoryView::OUTLINER_COLUMN_LASTVISITED  = 3;
  69. const int XFE_HistoryView::OUTLINER_COLUMN_EXPIRES      = 4;
  70. const int XFE_HistoryView::OUTLINER_COLUMN_VISITCOUNT   = 5;
  71.  
  72. /* pixmaps for use in the history window. */
  73. fe_icon XFE_HistoryView::historyIcon = { 0 };
  74.  
  75. XFE_HistoryView::XFE_HistoryView(XFE_Component *toplevel_component, 
  76.                    Widget parent,
  77.                    XFE_View *parent_view, MWContext *context) 
  78.   : XFE_View(toplevel_component, parent_view, context)
  79. {
  80.   int num_columns = 6;
  81.   static int column_widths[] = {35, 40, 25, 25, 25, 15};
  82.  
  83.   m_outliner = new XFE_Outliner("historyList",
  84.                                 this, 
  85.                                 getToplevel(),
  86.                                 parent,
  87.                                 False, // constantSize 
  88.                                 True,  // hasHeadings
  89.                                 num_columns,  // Number of columns.
  90.                                 num_columns,  // Number of visible columns.
  91.                                 column_widths, 
  92.                                 HISTORY_OUTLINER_GEOMETRY_PREF);
  93.  
  94.   m_outliner->setHideColumnsAllowed( TRUE );
  95.  
  96.   // is this the hierarchical stuff??
  97.   //  m_outliner->setPipeColumn( OUTLINER_COLUMN_TITLE );
  98.  
  99.   setBaseWidget(m_outliner->getBaseWidget());
  100.  
  101.   // Initialize clip stuff.
  102.   /*
  103.   clip.block = NULL;
  104.   clip.length = 0;
  105.   */
  106.   {
  107.     Pixel bg_pixel;
  108.     
  109.     XtVaGetValues(m_widget, XmNbackground, &bg_pixel, 0);
  110.  
  111.     if (!historyIcon.pixmap)
  112.       {
  113.         fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  114.                        BlackPixelOfScreen(XtScreen(m_widget)),
  115.                        bg_pixel,
  116.                        &historyIcon,
  117.                        NULL,
  118.                        HGroup.width, HGroup.height,
  119.                        HGroup.mono_bits, HGroup.color_bits,
  120.                        HGroup.mask_bits, FALSE);
  121.       }
  122.   }
  123.  
  124. #if defined(USE_MOTIF_DND)
  125.   m_outliner->enableDragDrop(this,
  126.                              NULL, /* no dropping -- of anything but outliner columns. */
  127.                              XFE_HistoryView::getDragTargets,
  128.                              XFE_HistoryView::getDragIconData,
  129.                              XFE_HistoryView::dragConvert);
  130.  
  131.   m_outliner->setMultiSelectAllowed(True);
  132. #else
  133.   m_outliner->setDragType(FE_DND_HISTORY, &historyIcon,
  134.                           this);
  135.   m_outliner->setMultiSelectAllowed(True);
  136.  
  137.   fe_dnd_CreateDrop(m_outliner->getBaseWidget(), drop_func, this);
  138.  
  139.  
  140. #endif /* USE_MOTIF_DND */
  141.  
  142.   m_filter = NULL;
  143.   m_sortBy = eHSC_LASTVISIT;
  144.   m_sortDescending = False;
  145.   m_selectList = XP_ListNew();
  146.  
  147.   m_outliner->setSortColumn(m_sortBy, OUTLINER_SortAscending );
  148.  
  149.   // Save vertical scroller for keyboard accelerators
  150.   CONTEXT_DATA(context)->vscroll = m_outliner->getScroller();
  151.  
  152.   refresh();
  153.  
  154.   // Select the first row
  155.   if (m_outliner->getTotalLines() > 0)
  156.     {
  157.       m_outliner->selectItemExclusive(0);
  158.     }
  159. }
  160.  
  161. XFE_HistoryView::~XFE_HistoryView()
  162. {
  163.   char *pszKey;
  164.   while( (pszKey = (char *)XP_ListRemoveTopObject( m_selectList )) )
  165.     {
  166.       delete [] pszKey;
  167.     }
  168.   XP_ListDestroy(m_selectList);
  169. }
  170.  
  171. Boolean
  172. XFE_HistoryView::isCommandEnabled(CommandType cmd, void *calldata,
  173.                                    XFE_CommandInfo* info)
  174. {
  175. #define IS_CMD(command) cmd == (command)
  176.   const int *selected;
  177.   int count;
  178.   
  179.   m_outliner->getSelection(&selected, &count);
  180.   
  181.   if (IS_CMD(xfeCmdOpenSelected)
  182.       || cmd == xfeCmdAddToToolbar
  183.       || cmd == xfeCmdAddBookmark
  184.       )
  185.     {
  186.       return count == 1;
  187.     } 
  188.   else if (
  189.            IS_CMD(xfeCmdSaveAs)
  190.            || IS_CMD(xfeCmdOpenSelected)
  191.  
  192.            || IS_CMD(xfeCmdSelectAll)
  193.  
  194.            || IS_CMD(xfeCmdSortByTitle)
  195.            || IS_CMD(xfeCmdSortByLocation)
  196.            || IS_CMD(xfeCmdSortByDateFirstVisited)
  197.            || IS_CMD(xfeCmdSortByDateLastVisited)
  198.            || IS_CMD(xfeCmdSortByExpirationDate)
  199.            || IS_CMD(xfeCmdSortByVisitCount)
  200.            || IS_CMD(xfeCmdSortAscending)
  201.            || IS_CMD(xfeCmdSortDescending)
  202.            //           || IS_CMD(xfeCmdMoreOptions)
  203.            //           || IS_CMD(xfeCmdFewerOptions)
  204.            || IS_CMD(xfeCmdEditPreferences)
  205.            )
  206.     {
  207.       return True;
  208.     } 
  209.   else if (
  210.            IS_CMD(xfeCmdPrintSetup)
  211.            || IS_CMD(xfeCmdPrint)
  212.  
  213.            || IS_CMD(xfeCmdUndo)
  214.            || IS_CMD(xfeCmdRedo)
  215.            || IS_CMD(xfeCmdCut)
  216.            || IS_CMD(xfeCmdCopy)
  217.            || IS_CMD(xfeCmdDelete)
  218.            || IS_CMD(xfeCmdSearch)
  219.            )
  220.     {
  221.       return False;
  222.     }
  223.   else
  224.     {
  225.       return XFE_View::isCommandEnabled(cmd, calldata, info);
  226.     }
  227. #undef IS_CMD
  228. }
  229.  
  230. void
  231. XFE_HistoryView::doCommand(CommandType cmd, void *calldata, XFE_CommandInfo*info)
  232. {
  233. #define IS_CMD(command) cmd == (command)
  234.  
  235.   if (
  236.       IS_CMD(xfeCmdPrintSetup)
  237.       || IS_CMD(xfeCmdPrint)
  238.       
  239.       || IS_CMD(xfeCmdUndo)
  240.       || IS_CMD(xfeCmdRedo)
  241.       || IS_CMD(xfeCmdCut)
  242.       || IS_CMD(xfeCmdCopy)
  243.       || IS_CMD(xfeCmdDelete)
  244.       || IS_CMD(xfeCmdSearch)
  245.       
  246.       //      || IS_CMD(xfeCmdMoreOptions)
  247.       //      || IS_CMD(xfeCmdFewerOptions)
  248.       )
  249.     {
  250.       DDD( printf("Unimplemented command: %s\n", Command::getString(cmd)); )
  251.       return;  //XXX do nothing for now
  252.     }
  253.   else if (IS_CMD(xfeCmdOpenSelected))
  254.     {
  255.       openSelected();
  256.       return;
  257.     }
  258.   else if (IS_CMD(xfeCmdSaveAs))
  259.     {
  260.       GH_FileSaveAsHTML( m_histCursor, getContext());
  261.       return;
  262.     }
  263.   else if (IS_CMD(xfeCmdSelectAll))
  264.     {
  265.       m_outliner->selectAllItems();
  266.     }
  267.   else if (IS_CMD(xfeCmdSortByTitle)
  268.            || IS_CMD(xfeCmdSortByLocation)
  269.            || IS_CMD(xfeCmdSortByDateFirstVisited)
  270.            || IS_CMD(xfeCmdSortByDateLastVisited)
  271.            || IS_CMD(xfeCmdSortByExpirationDate)
  272.            )
  273.     {
  274.       resort((enHistSortCol)calldata, False);
  275.       return;
  276.     }
  277.   else if (IS_CMD(xfeCmdSortByVisitCount))
  278.     {
  279.       resort((enHistSortCol)calldata, True);
  280.       return;
  281.     }
  282.   else if (IS_CMD(xfeCmdSortAscending))
  283.     {
  284.       resort(m_sortBy, False);
  285.       return;
  286.     }
  287.   else if (IS_CMD(xfeCmdSortDescending))
  288.     {
  289.       resort(m_sortBy, True);
  290.       return;
  291.     }
  292.   else if (IS_CMD(xfeCmdEditPreferences))
  293.     {
  294.       fe_showPreferences(getToplevel(), getContext());
  295.  
  296.       getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  297.       return;
  298.     }
  299.   else if (cmd == xfeCmdAddToToolbar)
  300.     {
  301.       const int *    selected;
  302.       int            count;
  303.         
  304.       m_outliner->getSelection(&selected, &count);
  305.       
  306.       if (count == 1 && selected[0] >= 0
  307.           && selected[0] < m_outliner->getTotalLines() - 1)
  308.         {
  309.           BM_Entry * personalTB =
  310.             XFE_PersonalToolbar::getToolbarFolder();
  311.           gh_HistEntry* gh_entry =
  312.             GH_GetRecord(m_histCursor, selected[0]);
  313.  
  314.           if (personalTB && gh_entry)
  315.             {
  316.               BM_Entry* entry = 
  317.                 BM_NewUrl(gh_entry->pszName,
  318.                           gh_entry->address,
  319.                           NULL,
  320.                           gh_entry->last_accessed);
  321.               
  322.               BM_AppendToHeader(fe_getBookmarkContext(),
  323.                                 personalTB, entry);
  324.             }
  325.         }
  326.     }
  327.   else if (cmd == xfeCmdAddBookmark)
  328.     {
  329.       const int *    selected;
  330.       int            count;
  331.         
  332.       m_outliner->getSelection(&selected, &count);
  333.       
  334.       if (count == 1 && selected[0] >= 0
  335.           && selected[0] < m_outliner->getTotalLines() - 1)
  336.         {
  337.           gh_HistEntry* gh_entry =
  338.             GH_GetRecord(m_histCursor, selected[0]);
  339.  
  340.           if (!gh_entry) return;
  341.  
  342.           BM_Entry* entry = 
  343.             BM_NewUrl(gh_entry->pszName,
  344.                       gh_entry->address,
  345.                       NULL,
  346.                       gh_entry->last_accessed);
  347.           
  348.           BM_AppendToHeader (XFE_BookmarkFrame::main_bm_context,
  349.                              BM_GetAddHeader(XFE_BookmarkFrame::main_bm_context), entry);
  350.         }
  351.     }
  352.   else
  353.     {
  354.       XFE_View::doCommand(cmd,calldata,info);
  355.     }
  356. #undef IS_CMD
  357. }
  358.  
  359. Boolean
  360. XFE_HistoryView::handlesCommand(CommandType cmd, void *calldata,
  361.                                  XFE_CommandInfo* info)
  362. {
  363. #define IS_CMD(command) cmd == (command)
  364.  
  365.   if (
  366.       IS_CMD(xfeCmdSaveAs)
  367.       || IS_CMD(xfeCmdOpenSelected)
  368.       || IS_CMD(xfeCmdAddToToolbar)
  369.       || IS_CMD(xfeCmdAddBookmark)
  370.       || IS_CMD(xfeCmdPrintSetup)
  371.       || IS_CMD(xfeCmdPrint)
  372.       
  373.       || IS_CMD(xfeCmdUndo)
  374.       || IS_CMD(xfeCmdRedo)
  375.       || IS_CMD(xfeCmdCut)
  376.       || IS_CMD(xfeCmdCopy)
  377.       || IS_CMD(xfeCmdDelete)
  378.       || IS_CMD(xfeCmdSelectAll)
  379.       || IS_CMD(xfeCmdSearch)
  380.  
  381.       || IS_CMD(xfeCmdSortByTitle)
  382.       || IS_CMD(xfeCmdSortByLocation)
  383.       || IS_CMD(xfeCmdSortByDateFirstVisited)
  384.       || IS_CMD(xfeCmdSortByDateLastVisited)
  385.       || IS_CMD(xfeCmdSortByExpirationDate)
  386.       || IS_CMD(xfeCmdSortByVisitCount)
  387.       || IS_CMD(xfeCmdSortAscending)
  388.       || IS_CMD(xfeCmdSortDescending)
  389.       //      || IS_CMD(xfeCmdMoreOptions)
  390.       //      || IS_CMD(xfeCmdFewerOptions)
  391.       || IS_CMD(xfeCmdEditPreferences)
  392.       )
  393.     {
  394.       return True;
  395.     }
  396.   else
  397.     {
  398.       return XFE_View::handlesCommand(cmd, calldata, info);
  399.     }
  400. #undef IS_CMD
  401. }
  402.  
  403. char *
  404. XFE_HistoryView::commandToString(CommandType, void*, XFE_CommandInfo*)
  405. {
  406.     return NULL;
  407. }
  408.  
  409. XP_Bool
  410. XFE_HistoryView::isCommandSelected(CommandType cmd,
  411.                                    void *calldata, XFE_CommandInfo* info)
  412. {
  413. #define IS_CMD(command) cmd == (command)
  414.  
  415.   // This method is designed for toggle button.
  416.   // We want to keep the toggle button to have the same state
  417.   //   as its matched view.
  418.  
  419.   if (IS_CMD(xfeCmdSortByTitle)
  420.       || IS_CMD(xfeCmdSortByLocation)
  421.       || IS_CMD(xfeCmdSortByDateFirstVisited)
  422.       || IS_CMD(xfeCmdSortByDateLastVisited)
  423.       || IS_CMD(xfeCmdSortByExpirationDate)
  424.       || IS_CMD(xfeCmdSortByVisitCount)
  425.       )
  426.     {
  427.       return m_sortBy == (enHistSortCol)calldata;
  428.     }
  429.   else if (IS_CMD(xfeCmdSortAscending))
  430.     {
  431.       return !m_sortDescending;
  432.     }
  433.   else if (IS_CMD(xfeCmdSortDescending))
  434.     {
  435.       return m_sortDescending;
  436.     }
  437.   else
  438.     {
  439.       XFE_View *view = getParent();
  440.       return (view && view->isCommandSelected(cmd, calldata, info));
  441.     }
  442.  
  443. #undef IS_CMD
  444. }
  445.  
  446. // Methods from the outlinable interface.
  447. void *
  448. XFE_HistoryView::ConvFromIndex(int index)
  449. {
  450.   return acquireLineData(index);
  451. }
  452.  
  453. int
  454. XFE_HistoryView::ConvToIndex(void */*item*/)
  455. {
  456.   // do we need this function?
  457.   XP_ASSERT(0);
  458.   return 0;
  459. }
  460.  
  461.  
  462. void *
  463. XFE_HistoryView::acquireLineData(int line)
  464. {
  465.   if( m_sortDescending )
  466.     {
  467.       m_entry = GH_GetRecord(m_histCursor, m_totalLines - 1 - line);
  468.     }
  469.   else
  470.     {
  471.       m_entry = GH_GetRecord(m_histCursor, line);
  472.     }
  473.  
  474.   return m_entry;
  475. }
  476.  
  477. void
  478. XFE_HistoryView::getTreeInfo(XP_Bool */*expandable*/,
  479.                   XP_Bool */*is_expanded*/,
  480.                   int *depth,
  481.                   OutlinerAncestorInfo **/*ancestor*/)
  482. {
  483.   depth = 0;
  484. }
  485.  
  486. EOutlinerTextStyle
  487. XFE_HistoryView::getColumnStyle(int /*column*/)
  488. {
  489.   return OUTLINER_Default;
  490. }
  491.  
  492. char *
  493. XFE_HistoryView::getColumnText(int column)
  494. {
  495.   static char title_buf[1024];
  496.   static char location_buf[1024];
  497.   static char first_visited_buf[1024];
  498.   static char last_visited_buf[1024];
  499.   static char expiration_date_buf[1024];
  500.   static char visit_count_buf[1024];
  501.  
  502.   XP_ASSERT(m_entry);
  503.  
  504.   switch (column)
  505.     {
  506.     case OUTLINER_COLUMN_TITLE:
  507.       {
  508.         char *title;
  509.         unsigned char *loc;
  510.       
  511.         title = m_entry->pszName;
  512.         loc = fe_ConvertToLocaleEncoding(INTL_DefaultWinCharSetID(NULL),
  513.                                          (unsigned char*)title);
  514.       
  515.         strcpy(title_buf, (const char *)loc);
  516.         title_buf[1023] = 0;
  517.       
  518.         if ((char *) loc != title)
  519.           {
  520.             XP_FREE(loc);
  521.           }
  522.       
  523.         return title_buf;
  524.       }
  525.     case OUTLINER_COLUMN_LOCATION:
  526.       {
  527.         if (m_entry->address)
  528.           {
  529.             strcpy(location_buf, m_entry->address);
  530.             location_buf[1023] = 0;
  531.       
  532.             return location_buf;
  533.           }
  534.       }
  535.     case OUTLINER_COLUMN_FIRSTVISITED:
  536.       {
  537.         struct tm* tmp;
  538.         
  539.         XP_ASSERT(m_entry);
  540.         
  541.         if (m_entry && m_entry->first_accessed != 0)
  542.           {
  543.             tmp = localtime(&(m_entry->first_accessed));
  544.             FE_StrfTime(getContext(), first_visited_buf, 1024,
  545.                         DATE_FORMAT, tmp);
  546.             return first_visited_buf;
  547.           }
  548.         return NULL;
  549.       }
  550.     case OUTLINER_COLUMN_LASTVISITED:
  551.       {
  552.         struct tm* tmp;
  553.         
  554.         XP_ASSERT(m_entry);
  555.         
  556.         if (m_entry && m_entry->last_accessed != 0)
  557.           {
  558.             tmp = localtime(&(m_entry->last_accessed));
  559.             FE_StrfTime(getContext(), last_visited_buf, 1024,
  560.                         DATE_FORMAT, tmp);
  561.             return last_visited_buf;
  562.           }
  563.         return NULL;
  564.       }
  565.     case OUTLINER_COLUMN_EXPIRES:
  566.       {
  567.         
  568.         int32 expireDays;
  569.         PREF_GetIntPref("browser.link_expiration",&expireDays);
  570.         
  571.         struct tm* tmp;
  572.         
  573.         XP_ASSERT(m_entry);
  574.         
  575.         if (m_entry && m_entry->last_accessed != 0)
  576.           {
  577.             time_t expireSecs = m_entry->last_accessed;
  578.             expireSecs += expireDays * 60 * 60 * 24;
  579.  
  580.             tmp = localtime(&expireSecs);
  581.             FE_StrfTime(getContext(), expiration_date_buf, 1024,
  582.                         DATE_FORMAT, tmp);
  583.             return expiration_date_buf;
  584.           }
  585.         return NULL;
  586.       }
  587.     case OUTLINER_COLUMN_VISITCOUNT:
  588.       {
  589.         XP_ASSERT(m_entry);
  590.         
  591.         if (m_entry && m_entry->iCount != 0)
  592.           {
  593.             sprintf(visit_count_buf, "%d", m_entry->iCount);
  594.             visit_count_buf[1023] = 0;
  595.             return visit_count_buf;
  596.           }
  597.         return NULL;
  598.       }
  599.     default:
  600.       XP_ASSERT(0);
  601.       return NULL;
  602.     }
  603. }
  604.  
  605. fe_icon *
  606. XFE_HistoryView::getColumnIcon(int column)
  607. {
  608.   XP_ASSERT(m_entry);
  609.   
  610.   if (column != OUTLINER_COLUMN_TITLE)
  611.     return NULL;
  612.   
  613.   return &historyIcon;
  614. }
  615.  
  616. char *
  617. XFE_HistoryView::getColumnName(int column)
  618. {
  619.     switch (column)
  620.         {
  621.         case OUTLINER_COLUMN_TITLE:
  622.             return "title";
  623.         case OUTLINER_COLUMN_LOCATION:
  624.             return "location";
  625.         case OUTLINER_COLUMN_FIRSTVISITED:
  626.             return "firstVisited";
  627.         case OUTLINER_COLUMN_LASTVISITED:
  628.             return "lastVisited";
  629.         case OUTLINER_COLUMN_EXPIRES:
  630.             return "expires";
  631.         case OUTLINER_COLUMN_VISITCOUNT:
  632.             return "visitCount";
  633.         default:
  634.             XP_ASSERT(0);
  635.             return 0;
  636.         }
  637. }
  638.  
  639. char *
  640. XFE_HistoryView::getColumnHeaderText(int column)
  641. {
  642.     switch (column)
  643.         {
  644.         case OUTLINER_COLUMN_TITLE:
  645.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_TITLE);
  646.         case OUTLINER_COLUMN_LOCATION:
  647.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_LOCATION);
  648.         case OUTLINER_COLUMN_FIRSTVISITED:
  649.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_FIRSTVISITED);
  650.         case OUTLINER_COLUMN_LASTVISITED:
  651.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_LASTVISITED);
  652.         case OUTLINER_COLUMN_EXPIRES:
  653.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_EXPIRES);
  654.         case OUTLINER_COLUMN_VISITCOUNT:
  655.             return XP_GetString(XFE_HISTORY_OUTLINER_COLUMN_VISITCOUNT);
  656.         default:
  657.             XP_ASSERT(0);
  658.             return 0;
  659.         }
  660. }
  661.  
  662. fe_icon *
  663. XFE_HistoryView::getColumnHeaderIcon(int /*column*/)
  664. {
  665.   return 0;
  666. }
  667.  
  668. EOutlinerTextStyle
  669. XFE_HistoryView::getColumnHeaderStyle(int /*column*/)
  670. {
  671.   return OUTLINER_Default;
  672. }
  673.  
  674. void
  675. XFE_HistoryView::releaseLineData()
  676. {
  677.   // nothing to do
  678.   return;
  679. }
  680.  
  681. void
  682. XFE_HistoryView::Buttonfunc(const OutlineButtonFuncData *data)
  683. {
  684.   if (data->row == -1) 
  685.     {
  686.       // sort based on a column
  687.  
  688.       enHistSortCol sortBy = (enHistSortCol)data->column;
  689.  
  690.       if (sortBy == m_sortBy)
  691.         {
  692.           resort(sortBy, !m_sortDescending);
  693.         }
  694.       else if (sortBy != eHSC_VISITCOUNT)
  695.         {
  696.           resort((enHistSortCol)data->column, False);
  697.         }
  698.       else
  699.         {
  700.           resort((enHistSortCol)data->column, True);
  701.         }
  702.       return;
  703.     }
  704.  
  705.   gh_HistEntry* entry = GH_GetRecord(m_histCursor, data->row);
  706.  
  707.   if (!entry) return;
  708.  
  709.   if (data->clicks == 1)
  710.     {
  711.       if (data->ctrl) 
  712.         {
  713.           if (m_outliner->isSelected(data->row))
  714.             m_outliner->deselectItem(data->row);
  715.           else
  716.             m_outliner->selectItem(data->row);
  717.         } 
  718.       else if (data->shift) 
  719.         {
  720.           // select the range.
  721.           const int *selected;
  722.           int count;
  723.       
  724.           m_outliner->getSelection(&selected, &count);
  725.       
  726.           if (count == 0) 
  727.             {
  728.               // there wasn't anything selected yet.
  729.               m_outliner->selectItemExclusive(data->row);
  730.             }
  731.           else if (count == 1)
  732.             {
  733.               // There was only one, so we select the range from
  734.               //    that item to the new one.
  735.               m_outliner->selectRangeByIndices(selected[0], data->row);
  736.             }
  737.           else
  738.             {
  739.               // we had a range of items selected, so let's do
  740.               // something really nice with them.
  741.               m_outliner->trimOrExpandSelection(data->row);
  742.             }
  743.         } 
  744.       else 
  745.         {
  746.           m_outliner->selectItemExclusive(data->row);
  747.         }
  748.     }
  749.   else if (data->clicks == 2) 
  750.     {
  751.       m_outliner->selectItemExclusive(data->row);
  752.       
  753.       openSelected();
  754.     }
  755.   
  756.   //  getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating);
  757. }
  758.  
  759. void
  760. XFE_HistoryView::Flippyfunc(const OutlineFlippyFuncData *data)
  761. {
  762. /*  gh_HistEntry* entry = GH_GetRecord(m_histCursor, data->row);
  763.   if (entry && BM_IsHeader(entry))
  764.     {
  765.       if (!BM_IsFolded(entry))
  766.     {
  767.       BM_ClearAllChildSelection((MWContext*)m_bmdata, entry, TRUE);
  768.     }
  769.  
  770.       BM_FoldHeader((MWContext*)m_bmdata, entry, !BM_IsFolded(entry), TRUE, FALSE);
  771.     }
  772.     */
  773.   DDD( printf("XFE_HistoryView::Flippyfunc(row = %d)\n", data->row+1); )
  774. }
  775.  
  776. XFE_Outliner *
  777. XFE_HistoryView::getOutliner()
  778. {
  779.   return m_outliner;
  780. }
  781.  
  782. void
  783. XFE_HistoryView::refreshCells(int first, int last, XP_Bool /*now*/)
  784. {
  785.   m_outliner->change(first - 1, last - first + 1, m_totalLines);
  786.  
  787.   //    fe_OutlineSetMaxDepth(BM_DATA(bm_context)->outline,
  788.   //              BM_GetMaxDepth(bm_context));
  789.  
  790.   DDD( printf("refreshCells %d to %d with %d total\n", first, last, 
  791.               m_totalLines); )
  792. }
  793.  
  794. void
  795. XFE_HistoryView::scrollIntoView(gh_HistEntry *entry)
  796. {
  797.   int num = GH_GetRecordNum(m_histCursor, entry->pszName);
  798.  
  799.   if (num > 0) 
  800.       m_outliner->makeVisible(num - 1);
  801. }
  802.  
  803. void
  804. XFE_HistoryView::setClipContents(void */*block*/, int32 /*length*/)
  805. {
  806.   freeClipContents();
  807.   
  808.   /*clip.block = XP_ALLOC(length);
  809.   XP_MEMCPY(clip.block, block, length);
  810.   clip.length = length;
  811. */
  812. }
  813.  
  814. void *
  815. XFE_HistoryView::getClipContents(int32 */*length*/)
  816. {
  817.   /*
  818.   if (length)
  819.     *length = clip.length;
  820.  
  821.   return (clip.block);
  822. */
  823.   return NULL;
  824. }
  825.  
  826. void
  827. XFE_HistoryView::freeClipContents()
  828. {
  829.   /*
  830. if (clip.block) XP_FREE(clip.block);
  831.  
  832.   clip.block = NULL;
  833.   clip.length = 0;
  834.   */
  835. }
  836. /*
  837. void
  838. XFE_HistoryView::openHistoryWindow()
  839. {
  840. #if 0
  841.   if (m_editshell)
  842.     {
  843.       makeEditItemDialog();
  844.       m_editentry = NULL;
  845.     }
  846.  
  847.   XtManageChild(m_editshell);
  848.   XMapRaised(XtDisplay(m_editshell), XtWindow(m_editshell));
  849. #endif
  850. }
  851. */
  852. #if !defined(USE_MOTIF_DND)
  853. void
  854. XFE_HistoryView::dropfunc(Widget /*dropw*/, fe_dnd_Event type,
  855.                            fe_dnd_Source *source, XEvent *event)
  856. {
  857.   int row = -1;
  858.   int x, y;
  859.   
  860.   /* we only understand these targets -- well, we only understand
  861.      the first two. The outliner understands the COLUMN one. */
  862.   if (source->type != FE_DND_COLUMN &&
  863.       source->type != FE_DND_URL &&
  864.       source->type != FE_DND_HISTORY)
  865.     {
  866.       return;
  867.     }
  868.   
  869.   if (source->type == FE_DND_COLUMN)
  870.     {
  871.       m_outliner->handleDragEvent(event, type, source);
  872.       
  873.       return;
  874.     }
  875.   
  876.   m_outliner->translateFromRootCoords(event->xbutton.x_root, event->xbutton.y_root, &x, &y);
  877.   
  878.   row = m_outliner->XYToRow(x, y);
  879.   
  880.   switch (type)
  881.     {
  882.     case FE_DND_START:
  883.       break;
  884.     case FE_DND_DRAG:
  885.       m_outliner->outlineLine(row);
  886.       break;
  887.     case FE_DND_DROP:
  888.       if (row >= 0)
  889.         {
  890.           if (source->type == FE_DND_HISTORY)
  891.             {
  892.               //BM_DoDrop(m_contextData, row + 1, FALSE);
  893.             }
  894.           else if (source->type == FE_DND_URL)
  895.             {
  896.             }
  897.           
  898.           // to clear the drag feedback.
  899.           m_outliner->outlineLine(-1);
  900.         }
  901.       break;
  902.     case FE_DND_END:
  903.       break;
  904.     }
  905. }
  906.  
  907. void
  908. XFE_HistoryView::drop_func(Widget dropw, void *closure, fe_dnd_Event type,
  909.                             fe_dnd_Source *source, XEvent* event)
  910. {
  911.     XFE_HistoryView *obj = (XFE_HistoryView*)closure;
  912.     
  913.     obj->dropfunc(dropw, type, source, event);
  914. }
  915. #endif /* USE_MOTIF_DND */
  916.  
  917. int
  918. XFE_HistoryView::notify(gh_NotifyMsg *msg)
  919. {
  920.   // Force a refresh now
  921.   // Eventually we should set a dirty flag and do this in the idle loop
  922.  
  923.   if (!m_dirty) 
  924.     {
  925.       m_dirty = TRUE;
  926.       XtAppAddTimeOut(XtWidgetToApplicationContext(getBaseWidget()),
  927.                       0,
  928.                       &XFE_HistoryView::refresh_cb,
  929.                       this);
  930.     }
  931.  
  932.  
  933.   if (msg->iNotifyMsg == GH_NOTIFY_UPDATE && msg->pszKey)
  934.     {
  935.       DDD( printf("notify: update %s\n",msg->pszKey); )
  936.     }
  937.   return TRUE;
  938. }
  939.  
  940. int
  941. XFE_HistoryView::notify_cb(gh_NotifyMsg *msg)
  942. {
  943.   XFE_HistoryView *obj = (XFE_HistoryView *)msg->pUserData;
  944.   
  945.   return obj->notify(msg);
  946. }
  947.  
  948. void 
  949. XFE_HistoryView::resort(enHistSortCol sortBy, XP_Bool sortDescending)
  950. {
  951.   if (m_sortBy != sortBy)
  952.     {
  953.       saveSelected();
  954.  
  955.       m_sortBy = sortBy;
  956.       m_sortDescending = sortDescending;
  957.       refresh();
  958.  
  959.       m_outliner->setSortColumn(m_sortBy, (m_sortDescending ? 
  960.                                            OUTLINER_SortDescending :
  961.                                            OUTLINER_SortAscending));
  962.  
  963.       restoreSelected();
  964.     }
  965.   else if (m_sortDescending != sortDescending)
  966.     {
  967.       // Just changing the order
  968.       m_sortDescending = sortDescending;
  969.  
  970.       m_outliner->toggleSortDirection();
  971.  
  972.       refreshCells(1, m_totalLines, TRUE);
  973.       reflectSelected();
  974.     }
  975. }
  976.  
  977. void
  978. XFE_HistoryView::refresh()
  979. {
  980.  
  981.   gh_SortColumn sortCol;
  982.  
  983.   if (m_sortBy < eHSC_EXPIRES)
  984.     {
  985.       sortCol = (gh_SortColumn)m_sortBy;
  986.     }
  987.   else if (m_sortBy == eHSC_EXPIRES)
  988.     {
  989.           sortCol = eGH_LastDateSort;
  990.     }
  991.   else
  992.     {
  993.       sortCol = eGH_VisitCountSort;
  994.     }
  995.   
  996.   m_histCursor = GH_GetContext(sortCol, m_filter, 
  997.                                &XFE_HistoryView::notify_cb,
  998.                                NULL, this );
  999.   
  1000.   XP_ASSERT( m_histCursor );
  1001.  
  1002.   // Initialize undo/redo support
  1003.   GH_SupportUndoRedo( m_histCursor );
  1004.  
  1005.   m_totalLines = GH_GetNumRecords( m_histCursor );
  1006.  
  1007.   refreshCells(1, m_totalLines, TRUE);
  1008.  
  1009.   m_dirty = FALSE;
  1010.  
  1011.   DDD( printf("Refresh history\n"); )
  1012. }
  1013.  
  1014. void
  1015. XFE_HistoryView::refresh_cb(XtPointer closure, XtIntervalId */*id*/)
  1016. {
  1017.   XFE_HistoryView *obj = (XFE_HistoryView *)closure;
  1018.  
  1019.   obj->saveSelected();
  1020.   obj->refresh();
  1021.   obj->restoreSelected();
  1022. }
  1023.  
  1024. gh_HistEntry *
  1025. XFE_HistoryView::getEntry(int index)
  1026. {
  1027.   if (index >= 0)
  1028.     {
  1029.       if( m_sortDescending )
  1030.         {
  1031.           return GH_GetRecord(m_histCursor, m_totalLines - 1 - index);
  1032.         }
  1033.       else
  1034.         {
  1035.           return GH_GetRecord(m_histCursor, index);
  1036.         }
  1037.     }
  1038.   else
  1039.     return NULL;
  1040. }
  1041.  
  1042. gh_HistEntry *
  1043. XFE_HistoryView::getSelection()
  1044. {
  1045.   const int *selected;
  1046.   int count;
  1047.   
  1048.   m_outliner->getSelection(&selected, &count);
  1049.   
  1050.   if (count >= 1)
  1051.     {
  1052.       if( m_sortDescending )
  1053.         {
  1054.           return GH_GetRecord(m_histCursor, m_totalLines - 1 - selected[0]);
  1055.         }
  1056.       else
  1057.         {
  1058.           return GH_GetRecord(m_histCursor, selected[0]);
  1059.         }
  1060.     }
  1061.   else
  1062.     return NULL;
  1063. }
  1064.  
  1065. void
  1066. XFE_HistoryView::openSelected()
  1067. {
  1068.   gh_HistEntry *entry = getSelection();
  1069.       
  1070.   if (entry)
  1071.     {
  1072.       fe_reuseBrowser(getContext(),
  1073.                       NET_CreateURLStruct(entry->address,
  1074.                                           NET_DONT_RELOAD));
  1075.     }
  1076. }
  1077.  
  1078. void 
  1079. XFE_HistoryView::reflectSelected()
  1080. {
  1081.   const int *selected;
  1082.   int count;
  1083.   
  1084.   m_outliner->getSelection(&selected, &count);
  1085.   m_outliner->deselectAllItems();
  1086.  
  1087.   if (selected && count > 0)
  1088.     for(int ii = 0; ii < count; ii++ )
  1089.       m_outliner->selectItem(m_totalLines - 1 - selected[ii]);
  1090. }
  1091.  
  1092. void
  1093. XFE_HistoryView::saveSelected()
  1094. {
  1095.   const int *selected;
  1096.   int count;
  1097.   
  1098.   m_outliner->getSelection(&selected, &count);
  1099.  
  1100.   if (selected && count > 0)
  1101.     {
  1102.       for(int ii = 0; ii < count; ii++ )
  1103.         {
  1104.           int itemNum = selected[ii];
  1105.           
  1106.           if( m_sortDescending )
  1107.             {
  1108.               itemNum = (m_totalLines - 1) - itemNum;
  1109.             }
  1110.           
  1111.           gh_HistEntry *record = GH_GetRecord( m_histCursor, itemNum );
  1112.           
  1113.           if( !record )
  1114.             {
  1115.               continue;
  1116.             }
  1117.           
  1118.           char *pszKey = new char[XP_STRLEN( record->address )+1];
  1119.           XP_STRCPY ( pszKey, record->address );
  1120.           XP_ListAddObject (m_selectList, pszKey);
  1121.         }
  1122.     }
  1123. }
  1124.  
  1125. void
  1126. XFE_HistoryView::restoreSelected()
  1127. {
  1128.   m_outliner->deselectAllItems();
  1129.  
  1130.   char *pszKey;
  1131.   while( (pszKey = (char *)XP_ListRemoveTopObject( m_selectList )) )
  1132.     {
  1133.       int itemNum =  GH_GetRecordNum( m_histCursor, pszKey );
  1134.  
  1135.       if( itemNum > -1 )
  1136.         {
  1137.           if( m_sortDescending )
  1138.             {
  1139.               itemNum = (m_totalLines - 1) - itemNum;
  1140.             }
  1141.           m_outliner->selectItem(itemNum);
  1142.         }
  1143.       delete [] pszKey;
  1144.     }
  1145. }
  1146.  
  1147. #if defined(USE_MOTIF_DND)
  1148.  
  1149. fe_icon_data *
  1150. XFE_HistoryView::GetDragIconData(int /*row*/, int /*column*/)
  1151. {
  1152.   DDD(printf("XFE_HistoryView::GetDragIconData()\n");)
  1153.   
  1154.   return &HGroup;
  1155. }
  1156.  
  1157. fe_icon_data *
  1158. XFE_HistoryView::getDragIconData(void *this_ptr,
  1159.                                 int row,
  1160.                                 int column)
  1161. {
  1162.   DDD(printf("XFE_HistoryView::getDragIconData()\n");)
  1163.   XFE_HistoryView *history_view = (XFE_HistoryView*)this_ptr;
  1164.  
  1165.   return history_view->GetDragIconData(row, column);
  1166. }
  1167.  
  1168. void
  1169. XFE_HistoryView::GetDragTargets(int row, int column,
  1170.                                 Atom **targets,
  1171.                                 int *num_targets)
  1172. {
  1173.   DDD(printf("XFE_HistoryView::GetDragTargets()\n");)
  1174.  
  1175.   int flags;
  1176.  
  1177.   XP_ASSERT(row > -1);
  1178.   if (row == -1)
  1179.     {
  1180.       *targets = NULL;
  1181.       *num_targets = 0;
  1182.     }
  1183.   else
  1184.     {
  1185.       *num_targets = 1;
  1186.       *targets = new Atom[ *num_targets ];
  1187.       
  1188.       (*targets)[0] = XFE_DragBase::_XA_NETSCAPE_URL;
  1189.       
  1190.       m_dragentry = GH_GetRecord(m_histCursor, row);
  1191.     }
  1192. }
  1193.  
  1194. void
  1195. XFE_HistoryView::getDragTargets(void *this_ptr,
  1196.                                 int row,
  1197.                                 int column,
  1198.                                 Atom **targets,
  1199.                                 int *num_targets)
  1200. {
  1201.   DDD(printf("XFE_HistoryView::getDragTargets()\n");)
  1202.   XFE_HistoryView *history_view = (XFE_HistoryView*)this_ptr;
  1203.  
  1204.   history_view->GetDragTargets(row, column, targets, num_targets);
  1205. }
  1206.  
  1207. char *
  1208. XFE_HistoryView::DragConvert(Atom atom)
  1209. {
  1210.   if (atom == XFE_DragBase::_XA_NETSCAPE_URL)
  1211.     {
  1212.       char *result;
  1213.  
  1214.       // translate drag data to NetscapeURL format
  1215.       XFE_URLDesktopType urlData;
  1216.       
  1217.       urlData.createItemList(1);
  1218.       urlData.url(0,m_dragentry->address);
  1219.       result = XtNewString(urlData.getString());
  1220.       
  1221.       return result;
  1222.     }
  1223.   else if (atom == XA_STRING)
  1224.     {
  1225.       return XtNewString(m_dragentry->address);
  1226.     }
  1227. }
  1228.  
  1229. char *
  1230. XFE_HistoryView::dragConvert(void *this_ptr,
  1231.                             Atom atom)
  1232. {
  1233.   XFE_HistoryView *history_view = (XFE_HistoryView*)this_ptr;
  1234.   
  1235.   return history_view->DragConvert(atom);
  1236. }
  1237.  
  1238. #endif /* USE_MOTIF_DND */
  1239.