/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * list.c: List support */ #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) /* List heads for garbage collection. */ static list_T *first_list = NULL; /* list of all lists */ /* * Add a watcher to a list. */ void list_add_watch(list_T *l, listwatch_T *lw) { lw->lw_next = l->lv_watch; l->lv_watch = lw; } /* * Remove a watcher from a list. * No warning when it isn't found... */ void list_rem_watch(list_T *l, listwatch_T *lwrem) { listwatch_T *lw, **lwp; lwp = &l->lv_watch; for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) { if (lw == lwrem) { *lwp = lw->lw_next; break; } lwp = &lw->lw_next; } } /* * Just before removing an item from a list: advance watchers to the next * item. */ void list_fix_watch(list_T *l, listitem_T *item) { listwatch_T *lw; for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) if (lw->lw_item == item) lw->lw_item = item->li_next; } /* * Allocate an empty header for a list. * Caller should take care of the reference count. */ list_T * list_alloc(void) { list_T *l; l = (list_T *)alloc_clear(sizeof(list_T)); if (l != NULL) { /* Prepend the list to the list of lists for garbage collection. */ if (first_list != NULL) first_list->lv_used_prev = l; l->lv_used_prev = NULL; l->lv_used_next = first_list; first_list = l; } return l; } /* * list_alloc() with an ID for alloc_fail(). */ list_T * list_alloc_id(alloc_id_T id UNUSED) { #ifdef FEAT_EVAL if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T))) return NULL; #endif return (list_alloc()); } /* * Allocate an empty list for a return value, with reference count set. * Returns OK or FAIL. */ int rettv_list_alloc(typval_T *rettv) { list_T *l = list_alloc(); if (l == NULL) return FAIL; rettv->v_lock = 0; rettv_list_set(rettv, l); return OK; } /* * Same as rettv_list_alloc() but uses an allocation id for testing. */ int rettv_list_alloc_id(typval_T *rettv, alloc_id_T id UNUSED) { #ifdef FEAT_EVAL if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T))) return FAIL; #endif return rettv_list_alloc(rettv); } /* * Set a list as the return value */ void rettv_list_set(typval_T *rettv, list_T *l) { rettv->v_type = VAR_LIST; rettv->vval.v_list = l; if (l != NULL) ++l->lv_refcount; } /* * Unreference a list: decrement the reference count and free it when it * becomes zero. */ void list_unref(list_T *l) { if (l != NULL && --l->lv_refcount <= 0) list_free(l); } /* * Free a list, including all non-container items it points to. * Ignores the reference count. */ static void list_free_contents(list_T *l) { listitem_T *item; for (item = l->lv_first; item != NULL; item = l->lv_first) { /* Remove the item before deleting it. */ l->lv_first = item->li_next; clear_tv(&item->li_tv); vim_free(item); } } /* * Go through the list of lists and free items without the copyID. * But don't free a list that has a watcher (used in a for loop), these * are not referenced anywhere. */ int list_free_nonref(int copyID) { list_T *ll; int did_free = FALSE; for (ll = first_list; ll != NULL; ll = ll->lv_used_next) if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { /* Free the List and ordinary items it contains, but don't recurse * into Lists and Dictionaries, they will be in the list of dicts * or list of lists. */ list_free_contents(ll); did_free = TRUE; } return did_free; } static void list_free_list(list_T *l) { /* Remove the list from the list of lists for garbage collection. */ if (l->lv_used_prev == NULL) first_list = l->lv_used_next; else l->lv_used_prev->lv_used_next = l->lv_used_next; if (l->lv_used_next != NULL) l->lv_used_next->lv_used_prev = l->lv_used_prev; vim_free(l); } void list_free_items(int copyID) { list_T *ll, *ll_next; for (ll = first_list; ll != NULL; ll = ll_next) { ll_next = ll->lv_used_next; if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { /* Free the List and ordinary items it contains, but don't recurse * into Lists and Dictionaries, they will be in the list of dicts * or list of lists. */ list_free_list(ll); } } } void list_free(list_T *l) { if (!in_free_unref_items) { list_free_contents(l); list_free_list(l); } } /* * Allocate a list item. * It is not initialized, don't forget to set v_lock. */ listitem_T * listitem_alloc(void) { return (listitem_T *)alloc(sizeof(listitem_T)); } /* * Free a list item. Also clears the value. Does not notify watchers. */ void listitem_free(listitem_T *item) { clear_tv(&item->li_tv); vim_free(item); } /* * Remove a list item from a List and free it. Also clears the value. */ void listitem_remove(list_T *l, listitem_T *item) { vimlist_remove(l, item, item); listitem_free(item); } /* * Get the number of items in a list. */ long list_len(list_T *l) { if (l == NULL) return 0L; return l->lv_len; } /* * Return TRUE when two lists have exactly the same values. */ int list_equal( list_T *l1, list_T *l2, int ic, /* ignore case for strings */ int recursive) /* TRUE when used recursively */ { listitem_T *item1, *item2; if (l1 == NULL || l2 == NULL) return FALSE; if (l1 == l2) return TRUE; if (list_len(l1) != list_len(l2)) return FALSE; for (item1 = l1->lv_first, item2 = l2->lv_first; item1 != NULL && item2 != NULL; item1 = item1->li_next, item2 = item2->li_next) if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) return FALSE; return item1 == NULL && item2 == NULL; } /* * Locate item with index "n" in list "l" and return it. * A negative index is counted from the end; -1 is the last item. * Returns NULL when "n" is out of range. */ listitem_T * list_find(list_T *l, long n) { listitem_T *item; long idx; if (l == NULL) return NULL; /* Negative index is relative to the end. */ if (n < 0) n = l->lv_len + n; /* Check for index out of range. */ if (n < 0 || n >= l->lv_len) return NULL; /* When there is a cached index may start search from there. */ if (l->lv_idx_item != NULL) { if (n < l->lv_idx / 2) { /* closest to the start of the list */ item = l->lv_first; idx = 0; } else if (n > (l->lv_idx + l->lv_len) / 2) { /* closest to the end of the list */ item = l->lv_last; idx = l->lv_len - 1; } else { /* closest to the cached index */ item = l->lv_idx_item; idx = l->lv_idx; } } else { if (n < l->lv_len / 2) { /* closest to the start of the list */ item = l->lv_first; idx = 0; } else { /* closest to the end of the list */ item = l->lv_last; idx = l->lv_len - 1; } } while (n > idx) { /* search forward */ item = item->li_next; ++idx; } while (n < idx) { /* search backward */ item = item->li_prev; --idx; } /* cache the used index */ l->lv_idx = idx; l->lv_idx_item = item; return item; } /* * Get list item "l[idx]" as a number. */ long list_find_nr( list_T *l, long idx, int *errorp) /* set to TRUE when something wrong */ { listitem_T *li; li = list_find(l, idx); if (li == NULL) { if (errorp != NULL) *errorp = TRUE; return -1L; } return (long)tv_get_number_chk(&li->li_tv, errorp); } /* * Get list item "l[idx - 1]" as a string. Returns NULL for failure. */ char_u * list_find_str(list_T *l, long idx) { listitem_T *li; li = list_find(l, idx - 1); if (li == NULL) { semsg(_(e_listidx), idx); return NULL; } return tv_get_string(&li->li_tv); } /* * Locate "item" list "l" and return its index. * Returns -1 when "item" is not in the list. */ long list_idx_of_item(list_T *l, listitem_T *item) { long idx = 0; listitem_T *li; if (l == NULL) return -1; idx = 0; for (li = l->lv_first; li != NULL && li != item; li = li->li_next) ++idx; if (li == NULL) return -1; return idx; } /* * Append item "item" to the end of list "l". */ void list_append(list_T *l, listitem_T *item) { if (l->lv_last == NULL) { /* empty list */ l->lv_first = item; l->lv_last = item; item->li_prev = NULL; } else { l->lv_last->li_next = item; item->li_prev = l->lv_last; l->lv_last = item; } ++l->lv_len; item->li_next = NULL; } /* * Append typval_T "tv" to the end of list "l". * Return FAIL when out of memory. */ int list_append_tv(list_T *l, typval_T *tv) { listitem_T *li = listitem_alloc(); if (li == NULL) return FAIL; copy_tv(tv, &li->li_tv); list_append(l, li); return OK; } /* * Add a dictionary to a list. Used by getqflist(). * Return FAIL when out of memory. */ int list_append_dict(list_T *list, dict_T *dict) { listitem_T *li = listitem_alloc(); if (li == NULL) return FAIL; li->li_tv.v_type = VAR_DICT; li->li_tv.v_lock = 0; li->li_tv.vval.v_dict = dict; list_append(list, li); ++dict->dv_refcount; return OK; } /* * Append list2 to list1. * Return FAIL when out of memory. */ int list_append_list(list_T *list1, list_T *list2) { listitem_T *li = listitem_alloc(); if (li == NULL) return FAIL; li->li_tv.v_type = VAR_LIST; li->li_tv.v_lock = 0; li->li_tv.vval.v_list = list2; list_append(list1, li); ++list2->lv_refcount; return OK; } /* * Make a copy of "str" and append it as an item to list "l". * When "len" >= 0 use "str[len]". * Returns FAIL when out of memory. */ int list_append_string(list_T *l, char_u *str, int len) { listitem_T *li = listitem_alloc(); if (li == NULL) return FAIL; list_append(l, li); li->li_tv.v_t
<?php $TRANSLATIONS = array(
"Feed already exists." => "Le flux existe déjà.",
"Error adding feed." => "Erreur lors de l'ajout du flux.",
"Feed added!" => "ux ajouté !",
"Error adding folder." => "Erreur lors de l'ajout du répertoire.",
"Folder added!" => "Répertoire ajouté !",
"Error removing feed." => "Erreur de suppression du flux.",
"Error removing folder." => "Erreur de suppression du répertoire.",
"No file path was submitted." => "Aucun chemin de fichier n'a été indiqué.",
"An error occurred while parsing the file." => "Une erreur est apparue lors de l'analyse du fichier.",
"Error updating feeds." => "Erreur de mise à jour des flux.",
"Starred" => "Favoris",
"New articles" => "Nouveaux articles",
"Feed loaded!" => "Flux chargé !",
"Error moving feed into folder." => "Erreur de déplacement du flux dans le répertoire.",
"File doesn't exist:" => "Le fichier n'existe pas :",
"Error setting all items as read." => "Erreur lors du marquage de tous les articles comme lus.",
"Error marking item as read." => "Erreur lors du marquage de l'article comme lu.",
"Error updating feed." => "Erreur de mise à jour du flux.",
"Feed updated!" => "Flux mis à jour !",
"Name of the folder cannot be empty." => "Le nom du répertoire ne peut-être vide.",
"Error" => "Erreur",
"Adding..." => "Ajout...",
"Add folder" => "Ajouter un répertoi