|
@@ -1,490 +0,0 @@
|
|
|
-/*
|
|
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
|
|
- * @copyright Ranides Atterwim
|
|
|
|
|
- * @license WTFPL
|
|
|
|
|
- * @url http://ranides.net/projects/assira
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
-package net.ranides.assira.text.format;
|
|
|
|
|
-
|
|
|
|
|
-import java.awt.Color;
|
|
|
|
|
-import java.awt.Font;
|
|
|
|
|
-import java.io.Serializable;
|
|
|
|
|
-import java.util.Iterator;
|
|
|
|
|
-import net.ranides.assira.math.Bitwise;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Klasa reprezentująca ciąg znaków razem z przypisanymi do nich atrybutami
|
|
|
|
|
- * (kolor tekstu, tła, czcionka, styl)
|
|
|
|
|
- * @author ranides
|
|
|
|
|
- */
|
|
|
|
|
-public abstract class AnsiCharSequence implements CharSequence, Serializable {
|
|
|
|
|
-
|
|
|
|
|
- private static final long serialVersionUID = 4L;
|
|
|
|
|
-
|
|
|
|
|
- private int hash;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Odczytuje z sekwencji znak o podanym indeksie. Zwraca wynik identyczny jak
|
|
|
|
|
- * {@link #charAt}. Metoda istniejąca w celu uzyskania pełnej kompatybilności
|
|
|
|
|
- * sekwencji znaków z konwencją JavaBeans.
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract char getCharAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca numer koloru tekstu przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Numer może być zamieniony na graficzną reprezentację za pomocą {@link AnsiColorScheme}.
|
|
|
|
|
- * @see #getComputedForeAt
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract int getForeAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca numer koloru tła przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Numer może być zamieniony na graficzną reprezentację za pomocą {@link AnsiColorScheme}.
|
|
|
|
|
- * @see #getComputedBackAt
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract int getBackAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca atrybuty przypisane do znaku o podanym indeksie.
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract int getFlagsAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca numer czcionki przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Numer może być zamieniony na graficzną reprezentację za pomocą {@link AnsiFontScheme}.
|
|
|
|
|
- * @see #getComputedFontAt
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract int getFontAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca wszystkie właściwości przypisane do znaku o podanym indeksie
|
|
|
|
|
- * (kolor, tło, czcionka, styl).
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public final AnsiAttr getAttrAt(int index) {
|
|
|
|
|
- return new AttrView(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Metoda opcjonalna: zwraca kolor tekstu przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Ogólnie metoda zwraca rozsądny wynik, jeśli obiekt został powiązany
|
|
|
|
|
- * z odpowiednim schematem kolorów
|
|
|
|
|
- * ({@link AnsiColorScheme}.
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract Color getComputedForeAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Metoda opcjonalna: zwraca kolor tła przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Ogólnie metoda zwraca rozsądny wynik, jeśli obiekt został powiązany
|
|
|
|
|
- * z odpowiednim schematem kolorów
|
|
|
|
|
- * ({@link AnsiColorScheme}.
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract Color getComputedBackAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Metoda opcjonalna: zwraca numer czcionki przypisany do znaku o podanym indeksie.
|
|
|
|
|
- * Ogólnie metoda zwraca rozsądny wynik, jeśli obiekt został powiązany
|
|
|
|
|
- * z odpowiednim schematem czcionek
|
|
|
|
|
- * ({@link AnsiFontScheme}.
|
|
|
|
|
- * @param index
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract Font getComputedFontAt(int index);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Zwraca schemat kolorów skojarzony z sekwencją znaków. Schemat powiązany
|
|
|
|
|
- * z sekwencją odpowiada za prawidłowe działanie metod {@link #getComputedFore},
|
|
|
|
|
- * {@link #getComputedBack}, {@link #getComputedFont} oraz pochodnych.
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public abstract AnsiScheme getScheme();
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setScheme(AnsiScheme scheme);
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setCharAt(int index, char value);
|
|
|
|
|
-
|
|
|
|
|
- public void replace(int index, CharSequence value) {
|
|
|
|
|
- for(int i=0, n = value.length(); i<n; i++) {
|
|
|
|
|
- setCharAt(index+i, value.charAt(i));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setBackAt(int index, int color) {
|
|
|
|
|
- setBack(index, index+1, color);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setForeAt(int index, int color) {
|
|
|
|
|
- setFore(index, index+1, color);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setFontAt(int index, int font) {
|
|
|
|
|
- setFont(index, index+1, font);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setFlagsAt(int index, int flags) {
|
|
|
|
|
- setFlags(index, index+1, flags);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void setAttrAt(int index, AnsiAttr attr) {
|
|
|
|
|
- setBackAt(index, attr.getBack());
|
|
|
|
|
- setForeAt(index, attr.getFore());
|
|
|
|
|
- setFontAt(index, attr.getFont());
|
|
|
|
|
- setFlagsAt(index, attr.getFlags());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setBack(int from, int to, int attr);
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setFore(int from, int to, int attr);
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setFont(int from, int to, int font);
|
|
|
|
|
-
|
|
|
|
|
- public abstract void setFlags(int from, int to, int flags);
|
|
|
|
|
-
|
|
|
|
|
- public final void setAttr(int from, int to, AnsiAttr attr) {
|
|
|
|
|
- setBack(from, to, attr.getBack());
|
|
|
|
|
- setFore(from, to, attr.getFore());
|
|
|
|
|
- setFont(from, to, attr.getFont());
|
|
|
|
|
- setFlags(from, to, attr.getFlags());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Rozbija tekst na fragmenty według kryterium {@link AnsiAttr#CMP_ALL}
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public final Iterable<AnsiRegion> regions() {
|
|
|
|
|
- return regions(AnsiAttr.CMP_ALL);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * <p>
|
|
|
|
|
- * Rozbija tekst na fragmenty zawierające znaki zgrupowane według kryteriów
|
|
|
|
|
- * podanych w opcjach. Opcje są zbiorem flag z klasy {@link AnsiAttr}.
|
|
|
|
|
- * </p><p>
|
|
|
|
|
- * Rozdziela tekst na fragmenty o jednym kolorze tekstu i tła:<br/>
|
|
|
|
|
- * {@code text.split(AnsiAttr.CMP_FORE | AnsiAttr.CMP_BACK)}
|
|
|
|
|
- * </p><p>
|
|
|
|
|
- * Rozdziela tekst na fragmenty o tym samym stylu pogrubienia:<br/>
|
|
|
|
|
- * {@code text.split(AnsiAttr.CMP_FLAGS | AnsiAttr.BOLD)}
|
|
|
|
|
- * </p>
|
|
|
|
|
- * @param options
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public Iterable<AnsiRegion> regions(final int options) {
|
|
|
|
|
- return () -> new RegionIterator(options);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public final char charAt(int index) {
|
|
|
|
|
- return getCharAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public AnsiCharSequence subSequence(int begin, int end) {
|
|
|
|
|
- return new Fragment(this, begin, end);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int hashCode() {
|
|
|
|
|
- int h = hash;
|
|
|
|
|
- int n = length();
|
|
|
|
|
- if (h == 0 && n>0) {
|
|
|
|
|
- for (int i = 0; i < n; i++) {
|
|
|
|
|
- h = 31 * h + charAt(i) + 37 * getBackAt(i) + 53 * getForeAt(i);
|
|
|
|
|
- }
|
|
|
|
|
- hash = h;
|
|
|
|
|
- }
|
|
|
|
|
- return h;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public boolean equals(Object object) {
|
|
|
|
|
- if(object instanceof AnsiCharSequence) {
|
|
|
|
|
- return equals((AnsiCharSequence)object, AnsiAttr.CMP_PUBLIC);
|
|
|
|
|
- }
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public boolean equals(AnsiCharSequence value, int flags) {
|
|
|
|
|
- if( this == value ) { // NOPMD
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- if( value.length() != length() ) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- for(int i=0, n=value.length(); i<n; i++) {
|
|
|
|
|
- if (Bitwise.has(flags, AnsiAttr.CMP_CHAR) && value.charAt(i) != charAt(i)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if( !value.getAttrAt(i).equals(getAttrAt(i), flags) ) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public final String toString() {
|
|
|
|
|
- return new StringBuilder(length()).append(this).toString();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private class RegionIterator implements Iterator<AnsiRegion> {
|
|
|
|
|
-
|
|
|
|
|
- private final int options;
|
|
|
|
|
- private int index = 0;
|
|
|
|
|
-
|
|
|
|
|
- public RegionIterator(int options) {
|
|
|
|
|
- this.options = options;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public boolean hasNext() {
|
|
|
|
|
- return index < AnsiCharSequence.this.length();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- @SuppressWarnings("PMD.CyclomaticComplexity")
|
|
|
|
|
- public AnsiRegion next() {
|
|
|
|
|
- final int start = index;
|
|
|
|
|
- final AttrView attr = new AttrView(start);
|
|
|
|
|
- final boolean sfc = Bitwise.has(options, AnsiAttr.CMP_FORE);
|
|
|
|
|
- final boolean sfb = Bitwise.has(options, AnsiAttr.CMP_BACK);
|
|
|
|
|
- final boolean sfs = Bitwise.has(options, AnsiAttr.CMP_FLAGS);
|
|
|
|
|
- final boolean sff = Bitwise.has(options, AnsiAttr.CMP_FONT);
|
|
|
|
|
-
|
|
|
|
|
- index++;
|
|
|
|
|
- int max = AnsiCharSequence.this.length();
|
|
|
|
|
- while(index<max) {
|
|
|
|
|
- if( sfc && getForeAt(index)!=attr.getFore()) { break; }
|
|
|
|
|
- if( sfb && getBackAt(index)!=attr.getBack() ) { break; }
|
|
|
|
|
- if( sfs && (getFlagsAt(index) & options)!=(attr.getFlags()&options)) { break; }
|
|
|
|
|
- if( sff && getFontAt(index)!=attr.getFont()) { break; }
|
|
|
|
|
- index++;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return new AnsiRegion(attr, subSequence(start, index));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void remove() {
|
|
|
|
|
- throw new UnsupportedOperationException("Strings are immutable.");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private class AttrView extends AnsiAttr {
|
|
|
|
|
-
|
|
|
|
|
- private static final long serialVersionUID = 3L;
|
|
|
|
|
-
|
|
|
|
|
- private final int index;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Tworzy obiekt reprezentujący atrybuty znaku o podanym indeksie, zapisanego
|
|
|
|
|
- * w podanej sekwencji. Modyfikacja powiązanej sekwencji natychmiast jest
|
|
|
|
|
- * widoczna w obiekcie.
|
|
|
|
|
- * @param sequence
|
|
|
|
|
- * @param index
|
|
|
|
|
- */
|
|
|
|
|
- public AttrView(int index) {
|
|
|
|
|
- this.index = index;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Color getComputedBack() {
|
|
|
|
|
- return getComputedBackAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Font getComputedFont() {
|
|
|
|
|
- return getComputedFontAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Color getComputedFore() {
|
|
|
|
|
- return getComputedForeAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getFlags() {
|
|
|
|
|
- return getFlagsAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getBack() {
|
|
|
|
|
- return getBackAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getFont() {
|
|
|
|
|
- return getFontAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getFore() {
|
|
|
|
|
- return getForeAt(index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static class Fragment extends AnsiCharSequence {
|
|
|
|
|
-
|
|
|
|
|
- private static final long serialVersionUID = 3L;
|
|
|
|
|
-
|
|
|
|
|
- protected final AnsiCharSequence source;
|
|
|
|
|
- protected final int left;
|
|
|
|
|
- protected final int right;
|
|
|
|
|
-
|
|
|
|
|
- public Fragment(AnsiCharSequence source, int left, int right) {
|
|
|
|
|
- this.source = source;
|
|
|
|
|
- this.left = left;
|
|
|
|
|
- this.right = right;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Color getComputedForeAt(int index) {
|
|
|
|
|
- return source.getComputedForeAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Color getComputedBackAt(int index) {
|
|
|
|
|
- return source.getComputedBackAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getForeAt(int index) {
|
|
|
|
|
- return source.getForeAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getBackAt(int index) {
|
|
|
|
|
- return source.getBackAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getFlagsAt(int index) {
|
|
|
|
|
- return source.getFlagsAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Font getComputedFontAt(int index) {
|
|
|
|
|
- return source.getComputedFontAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int getFontAt(int index) {
|
|
|
|
|
- return source.getFontAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public AnsiCharSequence subSequence(int begin, int end) {
|
|
|
|
|
- return new Fragment(source, left+begin, left+end);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int length() {
|
|
|
|
|
- return right - left;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public char getCharAt(int index) {
|
|
|
|
|
- return source.charAt(left + index);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public AnsiScheme getScheme() {
|
|
|
|
|
- return source.getScheme();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setScheme(AnsiScheme scheme) {
|
|
|
|
|
- source.setScheme(scheme);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setCharAt(int index, char value) {
|
|
|
|
|
- source.setCharAt(left + index, value);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setBackAt(int index, int color) {
|
|
|
|
|
- source.setBackAt(left+index, color);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setForeAt(int index, int color) {
|
|
|
|
|
- source.setForeAt(left+index, color);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setFontAt(int index, int font) {
|
|
|
|
|
- source.setFontAt(left+index, font);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setFlagsAt(int index, int flags) {
|
|
|
|
|
- source.setFlagsAt(left+index, flags);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setAttrAt(int index, AnsiAttr attr) {
|
|
|
|
|
- source.setAttrAt(left+index, attr);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setBack(int from, int to, int attr) {
|
|
|
|
|
- source.setBack(left + from, left + to, attr);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setFore(int from, int to, int attr) {
|
|
|
|
|
- source.setFore(left + from, left + to, attr);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setFont(int from, int to, int font) {
|
|
|
|
|
- source.setFont(left + from, left + to, font);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void setFlags(int from, int to, int flags) {
|
|
|
|
|
- source.setFlags(left + from, left + to, flags);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public boolean equals(Object object) {
|
|
|
|
|
- if(this == object) {
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- if (object instanceof Fragment) {
|
|
|
|
|
- final Fragment other = (Fragment)object;
|
|
|
|
|
- if( source == other.source ) {
|
|
|
|
|
- return (left == other.left) && (right == other.right);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return super.equals(object);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int hashCode() {
|
|
|
|
|
- return super.hashCode();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|