1 --- svtools/util/makefile.mk.orig 2003-06-05 22:18:51.000000000 -0500
2 +++ svtools/util/makefile.mk 2003-06-05 22:19:38.000000000 -0500
8 +SHL2STDLIBS+= $(EXPATASCII3RDLIB) `pkg-config --libs glib-2.0`
14 --- svtools/source/config/makefile.mk.orig 2003-06-05 22:19:59.000000000 -0500
15 +++ svtools/source/config/makefile.mk 2003-06-05 22:21:02.000000000 -0500
17 $(SLO)$/accessibilityoptions.obj \
18 $(SLO)$/cmdoptions.obj \
19 $(SLO)$/extendedsecurityoptions.obj \
20 - $(SLO)$/sourceviewconfig.obj
21 + $(SLO)$/sourceviewconfig.obj \
22 + $(SLO)$/recent-files.obj
26 +CFLAGS+=`pkg-config --cflags glib-2.0`
30 $(SLO)$/accelcfg.obj \
31 --- svtools/prj/build.lst.orig 2003-06-05 22:23:34.000000000 -0500
32 +++ svtools/prj/build.lst 2003-06-05 22:23:42.000000000 -0500
34 -st svtools : offuh toolkit ucbhelper unotools jpeg NULL
35 +st svtools : offuh toolkit ucbhelper unotools jpeg expat NULL
36 st svtools usr1 - all st_mkout NULL
37 st svtools\inc get - all st_inc NULL
38 st svtools\inc\sane get - all st_incsa NULL
39 --- svtools/inc/historyoptions.hxx.orig 2003-06-05 22:25:11.000000000 -0500
40 +++ svtools/inc/historyoptions.hxx 2003-06-05 22:26:05.000000000 -0500
42 @param "eHistory" select right history.
43 @param "sURL" URL to save in history
44 @param "sFilter" filter name to save in history
45 + @param "sMimeType" MIME type of the URL; used only for ePICKLIST.
46 @param "sTitle" document title to save in history
47 @param "sPassword" password to save in history
50 void AppendItem( EHistoryType eHistory ,
51 const ::rtl::OUString& sURL ,
52 const ::rtl::OUString& sFilter ,
53 + const ::rtl::OUString& sMimeType ,
54 const ::rtl::OUString& sTitle ,
55 const ::rtl::OUString& sPassword );
57 --- svtools/source/config/historyoptions.cxx.orig 2003-06-05 22:26:20.000000000 -0500
58 +++ svtools/source/config/historyoptions.cxx 2003-06-05 23:12:47.000000000 -0500
63 +#include "recent-files.hxx"
65 //_________________________________________________________________________________________________________________
67 //_________________________________________________________________________________________________________________
69 sal_uInt32 nPosition = FIXPROPERTYCOUNT; // step over first three readed size values! but count begins at 0!
70 // Get names/values for picklist.
71 // 4 subkeys for every item!
75 - for( sal_uInt32 nItem=0; nItem<nPicklistCount; ++nItem )
76 + for( nItem=0; nItem<nPicklistCount; ++nItem )
78 seqValues[nPosition] >>= aItem.sURL ;
82 m_aPicklist.push_back( aItem );
85 + /* The user may already have a pick list from OOo, so we have to skip over it --- we now fetch the list from GNOME */
86 + nPosition += nPicklistCount * 4;
88 + ::svt::RecentFileItem *items;
92 + ::svt::recentFilesGetList (&items, &nItems);
94 + aItem.sFilter = OUString ("", 0, RTL_TEXTENCODING_ASCII_US);
95 + aItem.sPassword = OUString ("", 0, RTL_TEXTENCODING_ASCII_US);
97 + for (i = 0; i < nItems; i++) {
98 + aItem.sURL = OUString(items[i].uri);
99 + aItem.sTitle = OUString (items[i].uri); /* We don't have a title, so just use the filename */
100 + m_aPicklist.push_back (aItem);
103 + ::svt::recentFilesFree (items, nItems);
105 // Attention: Don't reset nPosition here!
109 Sequence< PropertyValue > seqPropertyValues( 4 ) ;
113 // Copy picklist entries to save-list!
114 sal_uInt32 nPicklistCount = m_aPicklist.size();
115 - for( sal_uInt32 nItem=0; nItem<nPicklistCount; ++nItem )
116 + for( nItem=0; nItem<nPicklistCount; ++nItem )
118 aItem = m_aPicklist[nItem];
119 sNode = PROPERTYNAME_PICKLIST + PATHDELIMITER + FIXP + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER;
122 SetSetProperties( PROPERTYNAME_PICKLIST, seqPropertyValues );
126 // Copy URL-list entries to save-list!
127 sal_uInt32 nHistoryCount = m_aHistory.size();
128 for( nItem=0; nItem<nHistoryCount; ++nItem )
129 @@ -909,11 +935,16 @@
130 void SvtHistoryOptions::AppendItem( EHistoryType eHistory ,
131 const OUString& sURL ,
132 const OUString& sFilter ,
133 + const OUString& sMimeType ,
134 const OUString& sTitle ,
135 const OUString& sPassword )
137 MutexGuard aGuard( GetOwnStaticMutex() );
138 - m_pDataContainer->AppendItem( eHistory, sURL, sFilter, sTitle, sPassword );
140 + if (eHistory == ePICKLIST)
141 + ::svt::recentFilesAddItem (sURL.pData, sMimeType.pData);
143 + m_pDataContainer->AppendItem( eHistory, sURL, sFilter, sTitle, sPassword );
146 //*****************************************************************************************************************
147 --- sfx2/source/appl/newhelp.cxx.orig 2003-06-05 22:34:06.000000000 -0500
148 +++ sfx2/source/appl/newhelp.cxx 2003-06-05 22:35:03.000000000 -0500
149 @@ -1383,7 +1383,7 @@
151 String aTitle = GetEntry(i);
152 String* pURL = (String*)(ULONG)GetEntryData(i);
153 - aHistOpt.AppendItem( eHELPBOOKMARKS, rtl::OUString( *pURL ), sEmpty, rtl::OUString( aTitle ), sEmpty );
154 + aHistOpt.AppendItem( eHELPBOOKMARKS, rtl::OUString( *pURL ), sEmpty, sEmpty, rtl::OUString( aTitle ), sEmpty );
158 --- sfx2/source/appl/sfxpicklist.cxx.orig 2003-04-11 10:54:18.000000000 -0500
159 +++ sfx2/source/appl/sfxpicklist.cxx 2003-06-05 22:46:10.000000000 -0500
161 SvtHistoryOptions().AppendItem( eHISTORY,
162 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
166 SfxStringEncode( aURL.GetPass() ) );
168 @@ -497,17 +498,21 @@
170 ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
171 ::rtl::OUString aFilter;
172 + ::rtl::OUString aMimeType;
174 INetURLObject aURL( pMed->GetOrigURL() );
175 const SfxFilter* pFilter = pMed->GetOrigFilter();
179 aFilter = pFilter->GetFilterName();
180 + aMimeType = pFilter->GetMimeType();
183 // add to svtool history options
184 SvtHistoryOptions().AppendItem( ePICKLIST,
185 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
189 SfxStringEncode( aURL.GetPass() ) );
191 --- sd/source/ui/dlg/dlgass.cxx.orig 2003-06-05 23:00:04.000000000 -0500
192 +++ sd/source/ui/dlg/dlgass.cxx 2003-06-05 23:05:19.000000000 -0500
194 #include <sfx2/filedlghelper.hxx>
197 +#include <com/sun/star/system/XSystemShellExecute.hpp>
198 +#include <com/sun/star/document/XTypeDetection.hpp>
199 +#include <com/sun/star/util/URL.hpp>
200 +#include <com/sun/star/util/XURLTransformer.hpp>
201 +#include <sfx2/fcontnr.hxx>
203 #include "sdpage.hxx"
205 #include "assclass.hxx"
208 using namespace ::com::sun::star;
209 using namespace ::sd;
210 +using namespace ::com::sun::star::uno;
211 +using namespace ::com::sun::star::system;
214 void InterpolateFixedBitmap( FixedBitmap * pBitmap )
219 +/* Queries the name of the filter that we can use to open a file */
220 +static const String &
221 +getFilterNameForFile (rtl_uString *uri)
223 + Reference< ::com::sun::star::document::XTypeDetection > type_detection (
224 + ::comphelper::getProcessServiceFactory ()->createInstance (
225 + ::rtl::OUString::createFromAscii ("com.sun.star.comp.framework.TypeDetection" )),
228 + if (!type_detection.is())
231 + ::com::sun::star::util::URL url;
232 + ::rtl::OUString type_name;
234 + url.Complete = uri;
236 + Reference < ::com::sun::star::util::XURLTransformer > trans (
237 + ::comphelper::getProcessServiceFactory ()->createInstance (
238 + ::rtl::OUString::createFromAscii ("com.sun.star.util.URLTransformer" )),
241 + trans->parseStrict (url);
243 + type_name = type_detection->queryTypeByURL (url.Main);
244 + SfxFilterMatcher &filter_matcher = SFX_APP ()->GetFilterMatcher ();
245 + const SfxFilter *filter = filter_matcher.GetFilter4EA (type_name);
249 + return filter->GetFilterName ();
253 void AssistentDlgImpl::ScanDocmenu (void)
255 else if (aPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_PASSWORD)
256 aPropertySet[nProperty].Value >>= sPassword;
258 + sFilter = rtl::OUString (getFilterNameForFile (sURL.pData).GetBuffer ());
259 + if (sFilter.getLength () == 0)
262 // If the entry is an impress file then insert it into the
263 // history list and the list box.
264 uno::Any aFilterPropSet = xFilterFactory->getByName( sFilter );
265 --- svtools/source/config/recent-files.hxx 2003-01-30 04:24:37.000000000 -0600
266 +++ svtools/source/config/recent-files.hxx 2003-06-05 23:10:17.000000000 -0500
268 +#ifndef RECENT_FILES_HXX
269 +#define RECENT_FILES_HXX
271 +#ifndef _RTL_USTRING_
272 +#include <rtl/ustring.h>
279 +/* A recent file item */
280 +struct RecentFileItem {
281 + rtl_uString *uri; /* URI of the file */
282 + rtl_uString *mimeType; /* MIME type */
283 + time_t timestamp; /* Timestamp for when the item was added */
286 +/* Queries the list of recent file items for OpenOffice.org */
287 +void recentFilesGetList (RecentFileItem **items, int *nItems);
289 +/* Frees an array of RecentFileItem structures */
290 +void recentFilesFree (RecentFileItem *items, int nItems);
292 +/* Adds an item to the list of recent file items */
293 +void recentFilesAddItem (rtl_uString *uri, const rtl_uString *mimeType);
298 --- svtools/source/config/recent-files.cxx 2003-01-30 04:24:37.000000000 -0600
299 +++ svtools/source/config/recent-files.cxx 2003-06-05 23:28:52.000000000 -0500
305 +#include <sys/file.h>
307 +#include <tools/string.hxx>
308 +#include "expat/xmlparse.h"
309 +#include "recent-files.hxx"
315 +<?xml version="1.0"?>
318 + <URI>file:///home/federico/gedit.txt</URI>
319 + <Mime-Type>text/plain</Mime-Type>
320 + <Timestamp>1046485966</Timestamp>
322 + <Group>gedit</Group>
326 + <URI>file:///home/federico/gedit-2.2.0.tar.bz2</URI>
327 + <Mime-Type>application/x-bzip</Mime-Type>
328 + <Timestamp>1046209851</Timestamp>
336 +/* Name of the standard ~/.recently-used file */
337 +#define RECENT_FILE_NAME ".recently-used"
339 +/* Items without a MIME type get assigned this by default */
340 +#define APPLICATION_OCTET_STREAM "application/octet-stream"
342 +/* Buffer size for reading ~/.recently-used */
343 +#define BUFFER_SIZE 16384
345 +/* Maximum number of entries to keep before pruning */
346 +#define MAX_ITEMS 20
348 +/* The group we use for OO.o files */
349 +#define GROUP_OPENOFFICE_ORG "OpenOffice.org"
351 +/* Tags we understand in the ~/.recently-used XML */
352 +#define TAG_RECENT_FILES "RecentFiles"
353 +#define TAG_RECENT_ITEM "RecentItem"
354 +#define TAG_URI "URI"
355 +#define TAG_MIME_TYPE "Mime-Type"
356 +#define TAG_TIMESTAMP "Timestamp"
357 +#define TAG_PRIVATE "Private"
358 +#define TAG_GROUPS "Groups"
359 +#define TAG_GROUP "Group"
361 +/* Recent item as parsed from the file */
366 + gboolean isPrivate;
372 + STATE_BEGIN, /* No elements read yet */
373 + STATE_RECENT_FILES, /* Inside the toplevel RecentFiles element */
374 + STATE_RECENT_ITEM, /* Inside RecentItem */
375 + STATE_URI, /* Inside URI */
376 + STATE_MIME_TYPE, /* Inside Mime-Type */
377 + STATE_TIMESTAMP, /* Inside Timestamp */
378 + STATE_PRIVATE, /* Inside Private */
379 + STATE_GROUPS, /* Inside Groups */
380 + STATE_GROUP, /* Inside Group */
381 + STATE_END, /* Finished parsing the toplevel element */
382 + STATE_ERROR /* Bad XML */
385 +/* XML parsing context */
386 +struct ParseContext {
392 +/* Computes the name of the ~/.recent-files file */
394 +getRecentFilename (void)
396 + return g_strdup_printf ("%s/" RECENT_FILE_NAME, g_get_home_dir ());
399 +/* Returns whether a string is null or empty */
401 +stringIsEmpty (const char *s)
403 + return (s == NULL || strlen (s) == 0);
406 +/* Frees the contents of str, if any, and g_strdup()s the newStr into it */
408 +replaceString (char **str, const char *newStr, int newStrLen)
411 + *str = g_strndup (newStr, newStrLen);
414 +/* Creates a new item in the context as a result of entering a RecentItem element */
416 +startRecentItem (ParseContext *context)
420 + item = g_new (Item, 1);
423 + item->mimeType = NULL;
424 + item->timestamp = -1;
425 + item->isPrivate = FALSE;
426 + item->groups = NULL;
428 + context->items = g_slist_prepend (context->items, item);
433 +freeItem (Item *item)
437 + g_free (item->uri);
438 + g_free (item->mimeType);
440 + for (l = item->groups; l; l = l->next) {
446 + g_slist_free (item->groups);
451 +/* Terminates a RecentItem element by ensuring that the basic properties of the
452 + * current are fulfilled. If the URI is empty, removes the item from the
456 +endRecentItem (ParseContext *context)
461 + g_assert (context->items != NULL);
462 + item = context->items->data;
464 + if (stringIsEmpty (item->uri)) {
466 + context->items = g_slist_delete_link (context->items, context->items);
470 + if (stringIsEmpty (item->mimeType))
471 + replaceString (&item->mimeType, APPLICATION_OCTET_STREAM, strlen (APPLICATION_OCTET_STREAM));
473 + if (item->timestamp == -1)
474 + item->timestamp = time (NULL);
477 +/* Handles entering a Private element */
479 +startPrivate (ParseContext *context)
483 + g_assert (context->items != NULL);
484 + item = context->items->data;
486 + item->isPrivate = TRUE;
489 +/* Start element handler for the parser */
491 +startElementCb (void *data, const XML_Char *name, const XML_Char **attributes)
493 + ParseContext *context;
497 + if (context->state == STATE_ERROR || context->state == STATE_END)
500 + switch (context->state) {
502 + if (strcmp (name, TAG_RECENT_FILES) == 0)
503 + context->state = STATE_RECENT_FILES;
505 + context->state = STATE_ERROR;
508 + case STATE_RECENT_FILES:
509 + if (strcmp (name, TAG_RECENT_ITEM) == 0) {
510 + startRecentItem (context);
511 + context->state = STATE_RECENT_ITEM;
513 + context->state = STATE_ERROR;
516 + case STATE_RECENT_ITEM:
517 + if (strcmp (name, TAG_URI) == 0)
518 + context->state = STATE_URI;
519 + else if (strcmp (name, TAG_MIME_TYPE) == 0)
520 + context->state = STATE_MIME_TYPE;
521 + else if (strcmp (name, TAG_TIMESTAMP) == 0)
522 + context->state = STATE_TIMESTAMP;
523 + else if (strcmp (name, TAG_PRIVATE) == 0) {
524 + startPrivate (context);
525 + context->state = STATE_PRIVATE;
526 + } else if (strcmp (name, TAG_GROUPS) == 0)
527 + context->state = STATE_GROUPS;
529 + context->state = STATE_ERROR;
533 + case STATE_MIME_TYPE:
534 + case STATE_TIMESTAMP:
535 + case STATE_PRIVATE:
539 + context->state = STATE_ERROR;
543 + if (strcmp (name, TAG_GROUP) == 0)
544 + context->state = STATE_GROUP;
546 + context->state = STATE_ERROR;
550 + g_assert_not_reached ();
554 +/* End element handler for the parser */
556 +endElementCb (void *data, const XML_Char *name)
558 + ParseContext *context;
562 + switch (context->state) {
563 + case STATE_RECENT_FILES:
564 + if (strcmp (name, TAG_RECENT_FILES) == 0)
565 + context->state = STATE_END;
567 + context->state = STATE_ERROR;
570 + case STATE_RECENT_ITEM:
571 + if (strcmp (name, TAG_RECENT_ITEM) == 0) {
572 + endRecentItem (context);
573 + context->state = STATE_RECENT_FILES;
575 + context->state = STATE_ERROR;
579 + if (strcmp (name, TAG_URI) == 0)
580 + context->state = STATE_RECENT_ITEM;
582 + context->state = STATE_ERROR;
585 + case STATE_MIME_TYPE:
586 + if (strcmp (name, TAG_MIME_TYPE) == 0)
587 + context->state = STATE_RECENT_ITEM;
589 + context->state = STATE_ERROR;
592 + case STATE_TIMESTAMP:
593 + if (strcmp (name, TAG_TIMESTAMP) == 0)
594 + context->state = STATE_RECENT_ITEM;
596 + context->state = STATE_ERROR;
599 + case STATE_PRIVATE:
600 + if (strcmp (name, TAG_PRIVATE) == 0) {
601 + startPrivate (context); /* I don't know if expat calls the start or end element handler for <foo/> */
602 + context->state = STATE_RECENT_ITEM;
604 + context->state = STATE_ERROR;
608 + if (strcmp (name, TAG_GROUPS) == 0)
609 + context->state = STATE_RECENT_ITEM;
611 + context->state = STATE_ERROR;
615 + if (strcmp (name, TAG_GROUP) == 0)
616 + context->state = STATE_GROUPS;
618 + context->state = STATE_ERROR;
624 + context->state = STATE_ERROR;
628 + g_assert_not_reached ();
632 +/* Sets the timestamp field of an Item */
634 +setTimestamp (Item *item, const char *s, int len)
639 + dup = g_strndup (s, len);
640 + if (sscanf (dup, "%ld", &t) != 1)
641 + item->timestamp = -1;
643 + item->timestamp = t;
648 +/* Adds a group to an item */
650 +addGroup (Item *item, const char *s, int len)
654 + for (l = item->groups; l; l = l->next) {
658 + if (strncmp (group, s, len) == 0)
662 + item->groups = g_slist_prepend (item->groups, g_strndup (s, len));
665 +/* Handler for character data between tags */
667 +characterDataCb (void *data, const XML_Char *s, int len)
669 + ParseContext *context;
673 + item = context->items ? context->items->data : NULL;
675 + switch (context->state) {
677 + replaceString (&item->uri, s, len);
680 + case STATE_MIME_TYPE:
681 + replaceString (&item->mimeType, s, len);
684 + case STATE_TIMESTAMP:
685 + setTimestamp (item, s, len);
689 + addGroup (item, s, len);
693 + case STATE_RECENT_FILES:
694 + case STATE_RECENT_ITEM:
695 + case STATE_PRIVATE:
699 + /* Ignore character data that may appear elsewhere */
703 + g_assert_not_reached ();
707 +/* Creates an XML parser for .recent-files */
709 +createParser (ParseContext *context)
713 + parser = XML_ParserCreate (NULL);
717 + XML_SetUserData (parser, context);
718 + XML_SetElementHandler (parser, startElementCb, endElementCb);
719 + XML_SetCharacterDataHandler (parser, characterDataCb);
724 +/* Compares items by timestamps so as to sort them in DECREASING order */
726 +compareTimestampsCb (gconstpointer a, gconstpointer b, gpointer data)
732 + ta = ia->timestamp;
735 + tb = ib->timestamp;
737 + return (ta < tb) ? 1 : (ta > tb) ? -1 : 0;
740 +/* Returns whether an item has a certain group */
742 +hasGroup (Item *item, const char *group)
746 + for (l = item->groups; l; l = l->next) {
750 + if (strcmp (g, group) == 0)
757 +/* Removes the oldest items from the context */
759 +trimOldItems (ParseContext *context)
765 + l = context->items;
773 + if (hasGroup (item, GROUP_OPENOFFICE_ORG)) {
776 + if (i > MAX_ITEMS) {
778 + context->items = g_slist_remove_link (context->items, l);
779 + g_slist_free_1 (l);
787 +/* Parses the file and fills in the context */
789 +parse (FILE *file, ParseContext *context)
792 + char buf[BUFFER_SIZE];
794 + context->items = NULL;
795 + context->state = STATE_BEGIN;
797 + parser = createParser (context);
806 + len = fread (buf, 1, sizeof (buf), file);
812 + if (!XML_Parse (parser, buf, len, eof)) {
813 + context->state = STATE_ERROR;
821 + if (context->items)
822 + endRecentItem (context); /* Finish it off for if we terminated prematurely on error */
824 + XML_ParserFree (parser);
826 + context->items = g_slist_sort (context->items, compareTimestampsCb);
827 + trimOldItems (context);
830 +/* Frees the contents of a parse context */
832 +freeContext(ParseContext *context)
836 + for (l = context->items; l; l = l->next) {
843 + g_slist_free (context->items);
846 +/* Converts our items into exported structures */
848 +convertItems (ParseContext *context, RecentFileItem **items, int *nItems)
853 + /* Count items with the OpenOffice.org group */
856 + for (l = context->items; l; l = l->next) {
860 + if (hasGroup (item, GROUP_OPENOFFICE_ORG))
867 + /* Add only the items we want */
869 + *items = g_new (RecentFileItem, *nItems);
873 + for (l = context->items; l; l = l->next) {
878 + if (hasGroup (item, GROUP_OPENOFFICE_ORG)) {
879 + RecentFileItem *rfi;
881 + rfi = (*items) + i;
884 + rtl_string2UString (&rfi->uri, item->uri, strlen (item->uri), RTL_TEXTENCODING_UTF8, 0);
885 + rfi->mimeType = NULL;
886 + rtl_string2UString (&rfi->mimeType, item->mimeType, strlen (item->mimeType), RTL_TEXTENCODING_UTF8, 0);
888 + rfi->timestamp = item->timestamp;
895 +/* Opens ~/.recent-files and locks it. If something fails, returns NULL. */
902 + ParseContext context;
904 + filename = getRecentFilename ();
906 + file = fopen (filename, "r+");
912 + fd = fileno (file);
913 + if (lockf (fd, F_LOCK, 0) != 0) {
921 +/* Unlocks ~/.recent-files and closes it. */
923 +unlockAndClose (FILE *file)
927 + fd = fileno (file);
928 + lockf (fd, F_ULOCK, 0);
934 + * recentFilesGetList:
935 + * @items: Return value; pointer to an array of items. Should be freed with recentFilesFree().
936 + * @nItems: Return value; number of items returned.
938 + * Queries the list of GNOME recent file items.
941 +recentFilesGetList (RecentFileItem **items, int *nItems)
944 + ParseContext context;
949 + file = openAndLock ();
953 + parse (file, &context);
955 + unlockAndClose (file);
957 + convertItems (&context, items, nItems);
958 + freeContext (&context);
961 +/* Writes the ~/.recent-files file */
963 +writeXml (FILE *file, ParseContext *context)
967 + fputs ("<?xml version=\"1.0\"?>\n"
968 + "<" TAG_RECENT_FILES ">\n",
971 + for (l = context->items; l; l = l->next) {
977 + fputs (" <" TAG_RECENT_ITEM ">\n", file);
979 + " <" TAG_URI ">%s</" TAG_URI ">\n"
980 + " <" TAG_MIME_TYPE ">%s</" TAG_MIME_TYPE ">\n"
981 + " <" TAG_TIMESTAMP ">%ld</" TAG_TIMESTAMP ">\n"
983 + " <" TAG_GROUPS ">\n",
986 + (long) item->timestamp,
987 + item->isPrivate ? " <" TAG_PRIVATE "/>\n" : "");
989 + for (gl = item->groups; gl; gl = gl->next) {
994 + " <" TAG_GROUP ">%s</" TAG_GROUP ">\n",
998 + fputs (" </" TAG_GROUPS ">\n"
999 + " </" TAG_RECENT_ITEM ">\n",
1003 + fputs ("</" TAG_RECENT_FILES ">\n", file);
1007 + * recentFilesFree:
1008 + * @items: Array of items.
1009 + * @nItems: Number of items in the array.
1011 + * Frees an array of #RecentFileItem structures as returned by recentFilesGetList().
1014 +recentFilesFree (RecentFileItem *items, int nItems)
1018 + for (i = 0; i < nItems; i++) {
1019 + rtl_uString_release (items[i].uri);
1020 + rtl_uString_release (items[i].mimeType);
1027 + * recentFilesAddItem:
1028 + * @uri: URI to add.
1029 + * @mimeType: MIME type of the item.
1031 + * Adds an item to GNOME's recent files list. Automatically adds the "OpenOffice.org" group.
1034 +recentFilesAddItem (rtl_uString *uri, const rtl_uString *mimeType)
1037 + ParseContext context;
1039 + gboolean alreadyExists;
1041 + rtl_String *uriString;
1042 + rtl_String *mimeTypeString;
1044 + file = openAndLock ();
1048 + parse (file, &context);
1050 + alreadyExists = FALSE;
1053 + mimeTypeString = NULL;
1054 + rtl_uString2String (&uriString, uri->buffer, uri->length, RTL_TEXTENCODING_UTF8, 0);
1055 + rtl_uString2String (&mimeTypeString, mimeType->buffer, mimeType->length, RTL_TEXTENCODING_UTF8, 0);
1057 + for (l = context.items; l; l = l->next) {
1061 + if (strcmp (item->uri, uriString->buffer) == 0) {
1062 + g_free (item->mimeType);
1063 + item->mimeType = g_strdup (mimeTypeString->buffer);
1064 + item->timestamp = time (NULL);
1065 + alreadyExists = TRUE;
1070 + if (!alreadyExists) {
1073 + item = g_new (Item, 1);
1074 + item->uri = g_strdup (uriString->buffer);
1075 + item->mimeType = g_strdup (mimeTypeString->buffer);
1076 + item->timestamp = time (NULL);
1077 + item->isPrivate = FALSE;
1078 + item->groups = g_slist_prepend (NULL, g_strdup (GROUP_OPENOFFICE_ORG));
1080 + context.items = g_slist_prepend (context.items, item);
1083 + rtl_string_release (uriString);
1084 + rtl_string_release (mimeTypeString);
1086 + fd = fileno (file);
1088 + /* FIXME: perhaps we should do a write to a temporary file, then do an atomic rename() */
1091 + if (ftruncate (fd, 0) != 0)
1094 + writeXml (file, &context);
1098 + unlockAndClose (file);
1099 + freeContext (&context);