Support for columns with UPDATE event in CREATE TRIGGER (8.5).
authorguillaume <guillaume@a7884b65-44f6-0310-8a51-81a127f17b15>
Mon, 7 Dec 2009 15:12:27 +0000 (15:12 +0000)
committerguillaume <guillaume@a7884b65-44f6-0310-8a51-81a127f17b15>
Mon, 7 Dec 2009 15:12:27 +0000 (15:12 +0000)
Fixes #97.

git-svn-id: svn://svn.pgadmin.org/trunk/pgadmin3@8124 a7884b65-44f6-0310-8a51-81a127f17b15

CHANGELOG
pgadmin/dlg/dlgTrigger.cpp
pgadmin/include/dlg/dlgTrigger.h
pgadmin/include/schema/pgTrigger.h
pgadmin/schema/pgTrigger.cpp
pgadmin/ui/dlgTrigger.xrc
pgadmin/ui/xrcDialogs.cpp

index 48cebf4d0f4f1429232226999bf5be4ded364a0b..cf010e5412af4a4ff6e1eb5449789ca43b907609 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -36,6 +36,8 @@ Changes
 
 Date       Dev Ver     Change details
 ---------- --- ------  --------------
+2009-12-07 GL  1.12.0  Support for columns with UPDATE event in CREATE TRIGGER
+                       (8.5).
 2009-12-07 GL  1.12.0  Support for TRIGGER with WHEN clause (8.5).
 2009-12-07 GL  1.12.0  Use of wxColourPickerCtrl each time we need to choose a
                        color.
index 37c673fc79db6cb3afe2cb5f451df05ad057b54f..2ab4c430b68030d09b04689e17dcad11cbe9c94a 100644 (file)
 #define chkTruncate     CTRL_CHECKBOX("chkTruncate")
 #define txtWhen         CTRL_TEXT("txtWhen")
 #define txtBody         CTRL_SQLBOX("txtBody")
+#define btnAddCol       CTRL_BUTTON("btnAddCol")
+#define btnRemoveCol    CTRL_BUTTON("btnRemoveCol")
+#define lstColumns      CTRL_LISTVIEW("lstColumns")
 
-BEGIN_EVENT_TABLE(dlgTrigger, dlgProperty)
+
+BEGIN_EVENT_TABLE(dlgTrigger, dlgCollistProperty)
     EVT_RADIOBOX(XRCID("rdbFires"),                 dlgProperty::OnChange)
     EVT_CHECKBOX(XRCID("chkRow"),                   dlgProperty::OnChange)
     EVT_CHECKBOX(XRCID("chkInsert"),                dlgProperty::OnChange)
-    EVT_CHECKBOX(XRCID("chkUpdate"),                dlgProperty::OnChange)
+    EVT_CHECKBOX(XRCID("chkUpdate"),                dlgTrigger::OnChange)
     EVT_CHECKBOX(XRCID("chkDelete"),                dlgProperty::OnChange)
     EVT_CHECKBOX(XRCID("chkTruncate"),              dlgProperty::OnChange)
     EVT_TEXT(XRCID("cbFunction"),                   dlgTrigger::OnChangeFunc)
@@ -48,6 +52,10 @@ BEGIN_EVENT_TABLE(dlgTrigger, dlgProperty)
     EVT_TEXT(XRCID("txtArguments"),                 dlgProperty::OnChange)
     EVT_TEXT(XRCID("txtWhen"),                      dlgProperty::OnChange)
     EVT_STC_MODIFIED(XRCID("txtBody"),              dlgProperty::OnChangeStc)
+    EVT_LIST_ITEM_SELECTED(XRCID("lstColumns"),     dlgTrigger::OnSelectListCol)
+    EVT_COMBOBOX(XRCID("cbColumns"),                dlgTrigger::OnSelectComboCol)
+    EVT_BUTTON(XRCID("btnAddCol"),                  dlgTrigger::OnAddCol)
+    EVT_BUTTON(XRCID("btnRemoveCol"),               dlgTrigger::OnRemoveCol)
 END_EVENT_TABLE();
 
 
@@ -60,7 +68,7 @@ dlgProperty *pgTriggerFactory::CreateDialog(frmMain *frame, pgObject *node, pgOb
 
 
 dlgTrigger::dlgTrigger(pgaFactory *f, frmMain *frame, pgTrigger *node, pgTable *parentNode)
-: dlgProperty(f, frame, wxT("dlgTrigger"))
+: dlgCollistProperty(f, frame, wxT("dlgTrigger"), parentNode)
 {
     trigger=node;
     table=parentNode;
@@ -68,6 +76,8 @@ dlgTrigger::dlgTrigger(pgaFactory *f, frmMain *frame, pgTrigger *node, pgTable *
 
     txtBody->SetMarginType(1, wxSTC_MARGIN_NUMBER);
     txtBody->SetMarginWidth(1, ConvertDialogToPixels(wxPoint(16, 0)).x);
+
+    lstColumns->AddColumn(_("Column name"));
 }
 
 
@@ -77,6 +87,23 @@ pgObject *dlgTrigger::GetObject()
 }
 
 
+wxString dlgTrigger::GetColumns()
+{
+    wxString sql;
+
+    int pos;
+    // iterate cols
+    for (pos=0 ; pos < lstColumns->GetItemCount() ; pos++)
+    {
+        if (pos)
+            sql += wxT(", ");
+
+        sql += qtIdent(lstColumns->GetItemText(pos));
+    }
+    return sql;
+}
+
+
 int dlgTrigger::Go(bool modal)
 {
     if (trigger)
@@ -121,6 +148,12 @@ int dlgTrigger::Go(bool modal)
                        chkTruncate->Disable();
         else if (!connection->BackendMinimumVersion(8, 5))
             txtWhen->Disable();
+
+               wxArrayString colsArr = trigger->GetColumnList();
+        for (int colIdx=0,colsCount=colsArr.Count(); colIdx<colsCount; colIdx++)
+        {
+                   lstColumns->InsertItem(colIdx, colsArr.Item(colIdx));
+        }
     }
     else
     {
@@ -159,10 +192,48 @@ int dlgTrigger::Go(bool modal)
 
     }
 
-    return dlgProperty::Go(modal);
+    cbColumns->Disable();
+    btnAddCol->Disable();
+    btnRemoveCol->Disable();
+
+    return dlgCollistProperty::Go(modal);
 }
 
 
+void dlgTrigger::OnAddCol(wxCommandEvent &ev)
+{
+    wxString colName=cbColumns->GetValue();
+
+    if (!colName.IsEmpty())
+    {
+        long colIndex = lstColumns->InsertItem(lstColumns->GetItemCount(), colName);
+
+        cbColumns->Delete(cbColumns->GetCurrentSelection());
+        if (cbColumns->GetCount())
+            cbColumns->SetSelection(0);
+
+        CheckChange();
+        if (!cbColumns->GetCount())
+            btnAddCol->Disable();
+    }
+}
+
+
+void dlgTrigger::OnRemoveCol(wxCommandEvent &ev)
+{
+    long pos=lstColumns->GetSelection();
+    if (pos >= 0)
+    {
+        wxString colName=lstColumns->GetItemText(pos);
+
+        lstColumns->DeleteItem(pos);
+        cbColumns->Append(colName);
+
+        CheckChange();
+        btnRemoveCol->Disable();
+    }
+}
+
 wxString dlgTrigger::GetSql()
 {
     wxString sql;
@@ -205,6 +276,8 @@ wxString dlgTrigger::GetSql()
             if (actionCount++)
                 sql += wxT(" OR");
             sql += wxT(" UPDATE");
+            if (lstColumns->GetItemCount() > 0)
+                sql += wxT(" OF ") + GetColumns();
         }
         if (chkDelete->GetValue())
         {
@@ -259,6 +332,41 @@ pgObject *dlgTrigger::CreateObject(pgCollection *collection)
 }
 
 
+void dlgTrigger::OnChange(wxCommandEvent &ev)
+{
+    if (chkUpdate->GetValue())
+    {
+        cbColumns->Enable();
+    }
+    else
+    {
+        if (lstColumns->GetItemCount() > 0)
+        {
+            if (wxMessageBox(_("Removing the UPDATE event will cause the column list to be cleared. Do you wish to continue?"), _("Remove UPDATE event?"), wxYES_NO) == wxNO)
+            {
+                chkUpdate->SetValue(true);
+                return;
+            }
+
+            // Move all the columns back to the combo
+            for (int pos = lstColumns->GetItemCount(); pos > 0; pos--)
+            {
+                wxString colName = lstColumns->GetItemText(pos - 1);
+
+                lstColumns->DeleteItem(pos - 1);
+                cbColumns->Append(colName);
+            }
+        }
+
+        cbColumns->Disable();
+        btnAddCol->Disable();
+        btnRemoveCol->Disable();
+    }
+
+    CheckChange();
+}
+
+
 void dlgTrigger::OnChangeFunc(wxCommandEvent &ev)
 {
     cbFunction->GuessSelection(ev);
@@ -336,3 +444,31 @@ bool dlgTrigger::IsUpToDate()
 
 
 
+void dlgTrigger::OnSelectListCol(wxListEvent &ev)
+{
+    OnSelectCol();
+}
+
+void dlgTrigger::OnSelectComboCol(wxCommandEvent &ev)
+{
+    OnSelectCol();
+}
+
+void dlgTrigger::OnSelectCol()
+{
+       // Can't change the columns on an existing index.
+       if (trigger)
+               return;
+
+    if (lstColumns->GetSelection() != wxNOT_FOUND)
+        btnRemoveCol->Enable(true);
+    else
+        btnRemoveCol->Enable(false);
+
+    if (cbColumns->GetSelection() != wxNOT_FOUND && !cbColumns->GetValue().IsEmpty())
+        btnAddCol->Enable(true);
+    else
+        btnAddCol->Enable(false);
+}
+
+
index 0640bdaa242cce1566792330fa8bcb6d92916f7c..7d1e4ebea34eaad87f54d3a280f4264a8c8dd841 100644 (file)
@@ -18,7 +18,7 @@
 class pgTrigger;
 class pgTable;
 
-class dlgTrigger : public dlgProperty
+class dlgTrigger : public dlgCollistProperty
 {
 public:
     dlgTrigger(pgaFactory *factory, frmMain *frame, pgTrigger *trg, pgTable *sch);
@@ -29,12 +29,20 @@ public:
     pgObject *CreateObject(pgCollection *collection);
     pgObject *GetObject();
     void SetObject(pgObject *obj) { trigger = (pgTrigger*)obj; }
+    wxString GetColumns();
+
 
 private:
     pgTable *table;
     pgTrigger *trigger;
 
+    void OnChange(wxCommandEvent &ev);
     void OnChangeFunc(wxCommandEvent &ev);
+    void OnSelectComboCol(wxCommandEvent &ev);
+    void OnSelectListCol(wxListEvent &ev);
+    void OnSelectCol();
+    void OnAddCol(wxCommandEvent &ev);
+    void OnRemoveCol(wxCommandEvent &ev);
 
        virtual bool IsUpToDate();
 
index 1188d309d52e82d065c423ae4852fb87ec2cae8d..92a48c0cd74fbbca5eeb4ab372bab34dbd86e32d 100644 (file)
@@ -58,6 +58,11 @@ public:
     void iSetQuotedFullTable(const wxString &s) { quotedFullTable=s; }
     OID GetFunctionOid() const { return functionOid; }
     void iSetFunctionOid(const OID d) { functionOid=d; }
+    wxString GetQuotedColumns() const { return quotedColumns; }
+    wxString GetColumns() const { return columns; }
+       wxArrayString GetColumnList() const { return columnList; }
+    long GetColumnCount() const { return columnCount; }
+    void iSetColumnCount(const long l) { columnCount=l; }
 
     void SetDirty();
 
@@ -71,8 +76,13 @@ public:
 
     bool IsUpToDate();
 
+protected:
+    void ReadColumnDetails();
+
 private:
-    wxString function, quotedFullTable, arguments, when, language, source;
+    wxString function, quotedFullTable, arguments, when, language, source, columns, quotedColumns;
+       wxArrayString columnList;
+    long columnCount;
     OID functionOid;
     long triggerType;
     bool enabled;
index 4200f3ac1021cf77922fbe312c8c1cc441ff3f86..7caae4e4317f28665acbaa3ae89a760a9e2e22b1 100644 (file)
@@ -96,8 +96,12 @@ wxString pgTrigger::GetSql(ctlTree *browser)
             sql += wxT("CREATE TRIGGER ") + qtIdent(GetName());
 
         sql += wxT("\n  ") + GetFireWhen() 
-            + wxT(" ") + GetEvent()
-            + wxT("\n  ON ") + GetQuotedFullTable()
+            + wxT(" ") + GetEvent();
+
+        if (!GetQuotedColumns().IsEmpty())
+            sql += wxT(" OF ") + GetQuotedColumns();
+
+        sql += wxT("\n  ON ") + GetQuotedFullTable()
             + wxT("\n  FOR EACH ") + GetForEach();
         
         if (GetConnection()->BackendMinimumVersion(8, 5)
@@ -166,10 +170,59 @@ wxString pgTrigger::GetForEach() const
 
 
 
+void pgTrigger::ReadColumnDetails()
+{
+    if (!expandedKids && GetLanguage() != wxT("edbspl"))
+    {
+        expandedKids = true;
+
+               if (GetConnection()->BackendMinimumVersion(8, 5))
+        {
+            pgSet *res = ExecuteSet(
+                wxT("SELECT attname\n")
+                wxT("FROM pg_attribute,\n")
+                wxT("(SELECT tgrelid, unnest(tgattr) FROM pg_trigger\n")
+                wxT(" WHERE oid=") + GetOidStr() + wxT(") AS columns(tgrelid, colnum)\n")
+                wxT("WHERE colnum=attnum AND tgrelid=attrelid"));
+
+                   // Allocate memory to store column def
+                   if (res->NumRows()>0) columnList.Alloc(res->NumRows());
+
+            long i = 1;
+            columns = wxT("");
+            quotedColumns = wxT("");
+
+            while (!res->Eof())
+            {
+                if (i > 1)
+                {
+                    columns += wxT(", ");
+                    quotedColumns += wxT(", ");
+                }
+
+                columns += res->GetVal(wxT("attname"));
+                quotedColumns += res->GetVal(wxT("attname"));
+                               columnList.Add(res->GetVal(wxT("attname")));
+
+                i++;
+                res->MoveNext();
+            }
+        }
+        else
+        {
+            columns = wxT("");
+            quotedColumns = wxT("");
+        }
+    }
+}
+
+
 void pgTrigger::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *properties, ctlSQLBox *sqlPane)
 {
     if (!expandedKids && GetLanguage() != wxT("edbspl"))
     {
+        ReadColumnDetails();
+
         if (browser)
         {
             // if no browser present, function will not be appended to tree
@@ -195,6 +248,10 @@ void pgTrigger::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *pro
         properties->AppendItem(_("OID"), GetOid());
         properties->AppendItem(_("Fires"), GetFireWhen());
         properties->AppendItem(_("Event"), GetEvent());
+        if (!GetQuotedColumns().IsEmpty())
+        {
+            properties->AppendItem(_("Columns"), GetColumns());
+        }
         properties->AppendItem(_("For each"), GetForEach());
         if (GetLanguage() != wxT("edbspl"))
             properties->AppendItem(_("Function"), GetFunction() + wxT("(") + GetArguments() + wxT(")"));
index 87ba9196ad59a03f1cc8a258c00b0046a194a2d1..7af64e9d5b86e84959c39871c866d124304f6b42 100644 (file)
               </object>
             </object>
           </object>
+          <object class="notebookpage">
+            <label>Columns</label>
+            <object class="wxPanel" name="pnlColumns">
+              <object class="wxFlexGridSizer">
+                <cols>1</cols>
+                <rows>3</rows>
+                <growablecols>0</growablecols>
+                <growablerows>0</growablerows>
+                <object class="sizeritem">
+                  <object class="wxListCtrl" name="lstColumns">
+                    <style>wxLC_REPORT|wxLC_SINGLE_SEL</style>
+                  </object>
+                  <flag>wxEXPAND|wxALL</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxFlexGridSizer">
+                    <cols>2</cols>
+                    <rows>1</rows>
+                    <vgap>5</vgap>
+                    <hgap>5</hgap>
+                    <growablecols>1</growablecols>
+                    <growablerows>0</growablerows>
+                    <object class="sizeritem">
+                      <object class="wxStaticText" name="stColumns">
+                        <label>Column</label>
+                      </object>
+                      <flag>wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                      <border>4</border>
+                    </object>
+                    <object class="sizeritem">
+                      <object class="wxComboBox" name="cbColumns">
+                        <content/>
+                        <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+                      </object>
+                      <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT</flag>
+                      <border>4</border>
+                    </object>
+                  </object>
+                  <flag>wxEXPAND|wxALL</flag>
+                  <border>4</border>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxFlexGridSizer">
+                    <cols>4</cols>
+                    <growablecols>0</growablecols>
+                    <object class="spacer">
+                      <size>3,3d</size>
+                    </object>
+                    <object class="sizeritem">
+                      <object class="wxButton" name="btnAddCol">
+                        <label>Add</label>
+                      </object>
+                    </object>
+                    <object class="spacer">
+                      <size>3,3d</size>
+                    </object>
+                    <object class="sizeritem">
+                      <object class="wxButton" name="btnRemoveCol">
+                        <label>Remove</label>
+                        <size>50,-1d</size>
+                      </object>
+                    </object>
+                  </object>
+                  <flag>wxEXPAND|wxALL</flag>
+                  <border>4</border>
+                </object>
+              </object>
+            </object>
+          </object>
           <object class="notebookpage">
             <label>Body</label>
             <object class="wxPanel" name="pnlBody">
index 4d5dfec780b2504653b131089028a46e98c8f9a9..d0c790e838d16eb538f92bf3eb9d6cdafd2e4cbc 100644 (file)
@@ -21161,7 +21161,7 @@ static unsigned char xml_res_file_53[] = {
 116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,
 98,106,101,99,116,62,10,60,47,114,101,115,111,117,114,99,101,62,10};
 
-static size_t xml_res_size_54 = 11578;
+static size_t xml_res_size_54 = 14539;
 static unsigned char xml_res_file_54[] = {
 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,
 110,99,111,100,105,110,103,61,34,73,83,79,45,56,56,53,57,45,49,34,63,62,
@@ -21579,7 +21579,141 @@ static unsigned char xml_res_file_54[] = {
 32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
 32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,110,
 111,116,101,98,111,111,107,112,97,103,101,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,108,97,98,101,108,62,66,111,100,121,60,47,108,97,98,101,
+32,32,32,32,32,60,108,97,98,101,108,62,67,111,108,117,109,110,115,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,
+97,109,101,61,34,112,110,108,67,111,108,117,109,110,115,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,
+115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,114,111,119,115,62,51,60,47,114,111,119,115,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,
+101,99,111,108,115,62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,
+115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,
+119,97,98,108,101,114,111,119,115,62,48,60,47,103,114,111,119,97,98,108,
+101,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+76,105,115,116,67,116,114,108,34,32,110,97,109,101,61,34,108,115,116,67,
+111,108,117,109,110,115,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,76,67,95,82,69,80,
+79,82,84,124,119,120,76,67,95,83,73,78,71,76,69,95,83,69,76,60,47,115,116,
+121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,119,120,
+65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,
+101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60,47,99,
+111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,114,111,119,115,62,49,60,47,114,111,119,115,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,53,
+60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,104,103,97,112,62,53,60,47,104,103,97,112,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,
+97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,97,98,108,101,
+99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,62,48,60,47,103,
+114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,
+120,116,34,32,110,97,109,101,61,34,115,116,67,111,108,117,109,110,115,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,67,111,108,117,109,110,60,47,108,97,98,101,
+108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,
+78,95,67,69,78,84,82,69,95,86,69,82,84,73,67,65,76,124,119,120,84,79,80,
+124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,99,98,
+67,111,108,117,109,110,115,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,115,116,121,108,101,62,119,120,67,66,95,82,69,65,68,79,78,76,89,124,
+119,120,67,66,95,68,82,79,80,68,79,87,78,60,47,115,116,121,108,101,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,124,
+119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,
+124,119,120,84,79,80,124,119,120,76,69,70,84,124,119,120,82,73,71,72,84,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,52,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,
+115,62,52,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,
+62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,
+101,62,51,44,51,100,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,
+116,111,110,34,32,110,97,109,101,61,34,98,116,110,65,100,100,67,111,108,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,108,97,98,101,108,62,65,100,100,60,47,108,97,98,101,108,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,44,51,
+100,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,
+32,110,97,109,101,61,34,98,116,110,82,101,109,111,118,101,67,111,108,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,82,101,109,111,118,101,60,47,108,97,98,101,
+108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,115,105,122,101,62,53,48,44,45,49,100,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,69,88,80,65,78,68,124,119,120,65,76,76,60,47,102,108,97,103,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,52,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,110,111,
+116,101,98,111,111,107,112,97,103,101,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,66,111,100,121,60,47,108,97,98,101,
 108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
 32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,
 61,34,112,110,108,66,111,100,121,34,62,10,32,32,32,32,32,32,32,32,32,32,