Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 : #ifndef _SVX_DATANAVI_HXX
20 : #define _SVX_DATANAVI_HXX
21 :
22 : #include <vcl/dialog.hxx>
23 : #include <vcl/fixed.hxx>
24 : #include <vcl/lstbox.hxx>
25 : #include <vcl/menubtn.hxx>
26 : #include <vcl/msgbox.hxx>
27 : #include <vcl/tabctrl.hxx>
28 : #include <vcl/tabpage.hxx>
29 : #include <vcl/toolbox.hxx>
30 : #include <svtools/inettbc.hxx>
31 : #include <svtools/svmedit.hxx>
32 : #include <svtools/treelistbox.hxx>
33 : #include <sfx2/dockwin.hxx>
34 : #include <sfx2/ctrlitem.hxx>
35 : #include <svx/simptabl.hxx>
36 : #include <rtl/ref.hxx>
37 : #include <com/sun/star/beans/XPropertySet.hpp>
38 : #include <com/sun/star/container/XContainer.hpp>
39 : #include <com/sun/star/container/XNameContainer.hpp>
40 : #include <com/sun/star/frame/XFrame.hpp>
41 : #include <com/sun/star/xforms/XFormsUIHelper1.hpp>
42 : #include <com/sun/star/xforms/XModel.hpp>
43 : #include <com/sun/star/xforms/XSubmission.hpp>
44 : #include <com/sun/star/xml/dom/XNode.hpp>
45 : #include <com/sun/star/xml/dom/events/XEventTarget.hpp>
46 :
47 : #include "datalistener.hxx"
48 : #include <vector>
49 :
50 : // forward ---------------------------------------------------------------
51 :
52 : class FmFormShell;
53 :
54 : //========================================================================
55 : //............................................................................
56 : namespace svxform
57 : {
58 : //............................................................................
59 :
60 : enum DataGroupType
61 : {
62 : DGTUnknown = 0,
63 : DGTInstance,
64 : DGTSubmission,
65 : DGTBinding
66 : };
67 :
68 : enum DataItemType
69 : {
70 : DITNone = 0,
71 : DITText,
72 : DITAttribute,
73 : DITElement,
74 : DITBinding
75 : };
76 :
77 : struct ItemNode;
78 : class XFormsPage;
79 : class DataNavigatorWindow;
80 : class AddInstanceDialog;
81 :
82 : typedef ::com::sun::star::uno::Reference<
83 : ::com::sun::star::xforms::XFormsUIHelper1 > XFormsUIHelper1_ref;
84 : typedef ::com::sun::star::uno::Reference<
85 : ::com::sun::star::xml::dom::XNode > XNode_ref;
86 : typedef ::com::sun::star::uno::Reference<
87 : ::com::sun::star::beans::XPropertySet > XPropertySet_ref;
88 : typedef ::com::sun::star::uno::Reference<
89 : ::com::sun::star::xforms::XModel > XModel_ref;
90 : typedef ::com::sun::star::uno::Reference<
91 : ::com::sun::star::container::XContainer > XContainer_ref;
92 : typedef ::com::sun::star::uno::Reference<
93 : ::com::sun::star::container::XNameContainer > XNameContainer_ref;
94 : typedef ::com::sun::star::uno::Reference<
95 : ::com::sun::star::frame::XFrame > XFrame_ref;
96 : typedef ::com::sun::star::uno::Reference<
97 : ::com::sun::star::frame::XModel > XFrameModel_ref;
98 : typedef ::com::sun::star::uno::Reference<
99 : ::com::sun::star::xml::dom::events::XEventTarget > XEventTarget_ref;
100 : typedef ::com::sun::star::uno::Reference<
101 : ::com::sun::star::xforms::XSubmission > XSubmission_ref;
102 :
103 : typedef ::com::sun::star::uno::Sequence<
104 : ::com::sun::star::beans::PropertyValue > PropertyValue_seq;
105 :
106 : typedef std::vector< XContainer_ref > ContainerList;
107 : typedef std::vector< XEventTarget_ref > EventTargetList;
108 :
109 : //========================================================================
110 : class DataTreeListBox : public SvTreeListBox
111 : {
112 : private:
113 : XFormsPage* m_pXFormsPage;
114 : DataGroupType m_eGroup;
115 :
116 : protected:
117 : using SvTreeListBox::ExecuteDrop;
118 :
119 : public:
120 : DataTreeListBox( XFormsPage* pPage, DataGroupType _eGroup, const ResId& rResId );
121 : ~DataTreeListBox();
122 :
123 : virtual PopupMenu* CreateContextMenu( void );
124 : virtual void ExcecuteContextMenuAction( sal_uInt16 _nSelectedPopupEntry );
125 : virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt );
126 : virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt );
127 : virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel );
128 :
129 : void DeleteAndClear();
130 : void RemoveEntry( SvTreeListEntry* _pEntry );
131 : };
132 :
133 : //========================================================================
134 : class XFormsPage : public TabPage
135 : {
136 : private:
137 : ToolBox m_aToolBox;
138 : DataTreeListBox m_aItemList;
139 :
140 : XFormsUIHelper1_ref m_xUIHelper;
141 :
142 : DataNavigatorWindow* m_pNaviWin;
143 : bool m_bHasModel;
144 : DataGroupType m_eGroup;
145 : ImageList m_TbxImageList;
146 : // these strings are not valid on the Submission and Binding Page
147 : // mb: furthermore these are properties of an instance, thus
148 : // it would be much better to get/set them through the UIHelper
149 : // interface.
150 : String m_sInstanceName;
151 : String m_sInstanceURL;
152 : bool m_bLinkOnce;
153 :
154 : DECL_LINK(TbxSelectHdl, void *);
155 : DECL_LINK(ItemSelectHdl, void *);
156 :
157 : void AddChildren( SvTreeListEntry* _pParent,
158 : const ImageList& _rImgLst,
159 : const XNode_ref& _xNode );
160 : bool DoToolBoxAction( sal_uInt16 _nToolBoxID );
161 : SvTreeListEntry* AddEntry( ItemNode* _pNewNode, bool _bIsElement );
162 : SvTreeListEntry* AddEntry( const XPropertySet_ref& _rPropSet );
163 : void EditEntry( const XPropertySet_ref& _rPropSet );
164 : bool RemoveEntry();
165 :
166 : protected:
167 : virtual long Notify( NotifyEvent& rNEvt );
168 :
169 : public:
170 : XFormsPage( Window* pParent, DataNavigatorWindow* _pNaviWin, DataGroupType _eGroup );
171 : ~XFormsPage();
172 :
173 : virtual void Resize();
174 :
175 0 : inline bool HasModel() const { return m_bHasModel; }
176 : String SetModel( const XModel_ref& _xModel, sal_uInt16 _nPagePos );
177 : void ClearModel();
178 : String LoadInstance( const PropertyValue_seq& _xPropSeq,
179 : const ImageList& _rImgLst );
180 :
181 : bool DoMenuAction( sal_uInt16 _nMenuID );
182 : void EnableMenuItems( Menu* _pMenu );
183 :
184 : inline SvTreeListEntry* GetSelectedItem() const { return m_aItemList.FirstSelected(); }
185 0 : inline const String& GetInstanceName() const { return m_sInstanceName; }
186 0 : inline const String& GetInstanceURL() const { return m_sInstanceURL; }
187 0 : inline bool GetLinkOnce() const { return m_bLinkOnce; }
188 0 : inline void SetInstanceName( const String &name ) { m_sInstanceName=name; }
189 0 : inline void SetInstanceURL( const String &url ) { m_sInstanceURL=url; }
190 0 : inline void SetLinkOnce( bool bLinkOnce ) { m_bLinkOnce=bLinkOnce; }
191 :
192 : typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> XPropertySet_t;
193 : typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> XNode_t;
194 :
195 0 : inline XPropertySet_t GetBindingForNode( const XNode_t &xNode ) { return m_xUIHelper->getBindingForNode(xNode,true); }
196 0 : inline String GetServiceNameForNode( const XNode_t &xNode ) { return m_xUIHelper->getDefaultServiceNameForNode(xNode); }
197 0 : inline XFormsUIHelper1_ref GetXFormsHelper( void ) const { return m_xUIHelper; }
198 : };
199 :
200 : //========================================================================
201 :
202 : typedef std::vector< XFormsPage* > PageList;
203 : typedef ::rtl::Reference < DataListener > DataListener_ref;
204 :
205 : class DataNavigatorWindow : public Window
206 : {
207 : private:
208 :
209 : ListBox m_aModelsBox;
210 : MenuButton m_aModelBtn;
211 : TabControl m_aTabCtrl;
212 : MenuButton m_aInstanceBtn;
213 :
214 : XFormsPage* m_pInstPage;
215 : XFormsPage* m_pSubmissionPage;
216 : XFormsPage* m_pBindingPage;
217 :
218 : long m_nMinWidth;
219 : long m_nMinHeight;
220 : long m_nBorderHeight;
221 : sal_uInt16 m_nLastSelectedPos;
222 : bool m_bShowDetails;
223 : bool m_bIsNotifyDisabled;
224 : Size m_a2Size;
225 : Size m_a3Size;
226 : ImageList m_aItemImageList;
227 : PageList m_aPageList;
228 : ContainerList m_aContainerList;
229 : EventTargetList m_aEventTargetList;
230 : Timer m_aUpdateTimer;
231 :
232 : DataListener_ref m_xDataListener;
233 : XNameContainer_ref m_xDataContainer;
234 : XFrame_ref m_xFrame;
235 : XFrameModel_ref m_xFrameModel;
236 :
237 : DECL_LINK( ModelSelectHdl, ListBox * );
238 : DECL_LINK( MenuSelectHdl, MenuButton * );
239 : DECL_LINK( MenuActivateHdl, MenuButton * );
240 : DECL_LINK(ActivatePageHdl, void *);
241 : DECL_LINK(UpdateHdl, void *);
242 :
243 : XFormsPage* GetCurrentPage( sal_uInt16& rCurId );
244 : void LoadModels();
245 : void SetPageModel();
246 : void ClearAllPageModels( bool bClearPages );
247 : void InitPages();
248 : void CreateInstancePage( const PropertyValue_seq& _xPropSeq );
249 : bool HasFirstInstancePage() const;
250 : sal_uInt16 GetNewPageId() const;
251 :
252 : protected:
253 : virtual void Resize();
254 :
255 : public:
256 : DataNavigatorWindow( Window* pParent, SfxBindings* pBindings );
257 : ~DataNavigatorWindow();
258 :
259 : void SetDocModified();
260 : void NotifyChanges( bool _bLoadAll = false );
261 : void AddContainerBroadcaster( const XContainer_ref& xContainer );
262 : void AddEventBroadcaster( const XEventTarget_ref& xTarget );
263 : void RemoveBroadcaster();
264 :
265 0 : inline const ImageList& GetItemImageList() const { return m_aItemImageList; }
266 0 : inline bool IsShowDetails() const { return m_bShowDetails; }
267 0 : inline void DisableNotify( bool _bDisable ) { m_bIsNotifyDisabled = _bDisable; }
268 : };
269 :
270 : //========================================================================
271 : class DataNavigator : public SfxDockingWindow, public SfxControllerItem
272 : {
273 : private:
274 : DataNavigatorWindow m_aDataWin;
275 :
276 : protected:
277 : virtual void Resize();
278 : virtual sal_Bool Close();
279 : virtual void GetFocus();
280 : virtual Size CalcDockingSize( SfxChildAlignment );
281 : virtual SfxChildAlignment CheckAlignment( SfxChildAlignment, SfxChildAlignment );
282 :
283 : public:
284 : DataNavigator( SfxBindings* pBindings, SfxChildWindow* pMgr, Window* pParent );
285 : virtual ~DataNavigator();
286 :
287 : using Window::Update;
288 : using SfxDockingWindow::StateChanged;
289 :
290 : void Update( FmFormShell* pFormShell );
291 : void StateChanged( sal_uInt16 nSID, SfxItemState eState,
292 : const SfxPoolItem* pState );
293 : };
294 :
295 : //========================================================================
296 0 : class SVX_DLLPUBLIC DataNavigatorManager : public SfxChildWindow
297 : {
298 : public:
299 : SVX_DLLPRIVATE DataNavigatorManager( Window* pParent, sal_uInt16 nId,
300 : SfxBindings* pBindings, SfxChildWinInfo* pInfo );
301 : SFX_DECL_CHILDWINDOW( DataNavigatorManager );
302 : };
303 :
304 : //========================================================================
305 : class AddDataItemDialog : public ModalDialog
306 : {
307 : private:
308 :
309 : FixedLine m_aItemFL;
310 : FixedText m_aNameFT;
311 : Edit m_aNameED;
312 : FixedText m_aDefaultFT;
313 : Edit m_aDefaultED;
314 : PushButton m_aDefaultBtn;
315 :
316 : FixedLine m_aSettingsFL;
317 : FixedText m_aDataTypeFT;
318 : ListBox m_aDataTypeLB;
319 :
320 : CheckBox m_aRequiredCB;
321 : PushButton m_aRequiredBtn;
322 : CheckBox m_aRelevantCB;
323 : PushButton m_aRelevantBtn;
324 : CheckBox m_aConstraintCB;
325 : PushButton m_aConstraintBtn;
326 : CheckBox m_aReadonlyCB;
327 : PushButton m_aReadonlyBtn;
328 : CheckBox m_aCalculateCB;
329 : PushButton m_aCalculateBtn;
330 :
331 : FixedLine m_aButtonsFL;
332 : OKButton m_aOKBtn;
333 : CancelButton m_aEscBtn;
334 : HelpButton m_aHelpBtn;
335 :
336 : XFormsUIHelper1_ref m_xUIHelper;
337 : XPropertySet_ref m_xBinding;
338 : XPropertySet_ref m_xTempBinding;
339 :
340 : ItemNode* m_pItemNode;
341 : DataItemType m_eItemType;
342 : String m_sFL_Element;
343 : String m_sFL_Attribute;
344 : String m_sFL_Binding;
345 : String m_sFT_BindingExp;
346 :
347 : DECL_LINK( CheckHdl, CheckBox * );
348 : DECL_LINK( ConditionHdl, PushButton * );
349 : DECL_LINK(OKHdl, void *);
350 :
351 : void InitDialog();
352 : void InitFromNode();
353 : void InitDataTypeBox();
354 :
355 : public:
356 : AddDataItemDialog(
357 : Window* pParent, ItemNode* _pNode, const XFormsUIHelper1_ref& _rUIHelper );
358 : ~AddDataItemDialog();
359 :
360 : void InitText( DataItemType _eType );
361 : };
362 :
363 : //========================================================================
364 : class AddConditionDialog : public ModalDialog
365 : {
366 : private:
367 : FixedText m_aConditionFT;
368 : MultiLineEdit m_aConditionED;
369 : FixedText m_aResultFT;
370 : FixedText m_aResultWin;
371 : PushButton m_aEditNamespacesBtn;
372 : FixedLine m_aButtonsFL;
373 : OKButton m_aOKBtn;
374 : CancelButton m_aEscBtn;
375 : HelpButton m_aHelpBtn;
376 :
377 : Timer m_aResultTimer;
378 : ::rtl::OUString m_sPropertyName;
379 :
380 : XFormsUIHelper1_ref m_xUIHelper;
381 : XPropertySet_ref m_xBinding;
382 :
383 : DECL_LINK(ModifyHdl, void *);
384 : DECL_LINK(ResultHdl, void *);
385 : DECL_LINK(EditHdl, void *);
386 : DECL_LINK(OKHdl, void *);
387 :
388 : public:
389 : AddConditionDialog( Window* pParent,
390 : const ::rtl::OUString& _rPropertyName, const XPropertySet_ref& _rBinding );
391 : ~AddConditionDialog();
392 :
393 0 : inline XFormsUIHelper1_ref GetUIHelper() const { return m_xUIHelper; }
394 0 : inline String GetCondition() const { return m_aConditionED.GetText(); }
395 : inline void SetCondition( const String& _rCondition );
396 : };
397 :
398 0 : inline void AddConditionDialog::SetCondition( const String& _rCondition )
399 : {
400 0 : m_aConditionED.SetText( _rCondition );
401 0 : m_aResultTimer.Start();
402 0 : }
403 :
404 : //========================================================================
405 : class NamespaceItemDialog : public ModalDialog
406 : {
407 : private:
408 : typedef std::vector< ::rtl::OUString > PrefixList;
409 :
410 : FixedText m_aNamespacesFT;
411 : SvxSimpleTableContainer m_aNamespacesListContainer;
412 : SvxSimpleTable m_aNamespacesList;
413 : PushButton m_aAddNamespaceBtn;
414 : PushButton m_aEditNamespaceBtn;
415 : PushButton m_aDeleteNamespaceBtn;
416 : FixedLine m_aButtonsFL;
417 : OKButton m_aOKBtn;
418 : CancelButton m_aEscBtn;
419 : HelpButton m_aHelpBtn;
420 :
421 : AddConditionDialog* m_pConditionDlg;
422 : PrefixList m_aRemovedList;
423 :
424 : XNameContainer_ref& m_rNamespaces;
425 :
426 : DECL_LINK( SelectHdl, SvxSimpleTable * );
427 : DECL_LINK( ClickHdl, PushButton * );
428 : DECL_LINK(OKHdl, void *);
429 :
430 : void LoadNamespaces();
431 :
432 : public:
433 : NamespaceItemDialog( AddConditionDialog* pParent, XNameContainer_ref& _rContainer );
434 : ~NamespaceItemDialog();
435 : };
436 :
437 : //========================================================================
438 : class ManageNamespaceDialog : public ModalDialog
439 : {
440 : private:
441 : FixedText m_aPrefixFT;
442 : Edit m_aPrefixED;
443 : FixedText m_aUrlFT;
444 : Edit m_aUrlED;
445 : FixedLine m_aButtonsFL;
446 : OKButton m_aOKBtn;
447 : CancelButton m_aEscBtn;
448 : HelpButton m_aHelpBtn;
449 :
450 : AddConditionDialog* m_pConditionDlg;
451 :
452 : DECL_LINK(OKHdl, void *);
453 :
454 : public:
455 : ManageNamespaceDialog( Window* pParent, AddConditionDialog* _pCondDlg, bool _bIsEdit );
456 : ~ManageNamespaceDialog();
457 :
458 : inline void SetNamespace( const String& _rPrefix, const String& _rURL );
459 0 : inline String GetPrefix() const { return m_aPrefixED.GetText(); }
460 0 : inline String GetURL() const { return m_aUrlED.GetText(); }
461 : };
462 :
463 0 : void ManageNamespaceDialog::SetNamespace( const String& _rPrefix, const String& _rURL )
464 : {
465 0 : m_aPrefixED.SetText( _rPrefix );
466 0 : m_aUrlED.SetText( _rURL );
467 0 : }
468 :
469 : //========================================================================
470 : class AddSubmissionDialog : public ModalDialog
471 : {
472 : private:
473 : FixedLine m_aSubmissionFL;
474 : FixedText m_aNameFT;
475 : Edit m_aNameED;
476 : FixedText m_aActionFT;
477 : Edit m_aActionED;
478 : FixedText m_aMethodFT;
479 : ListBox m_aMethodLB;
480 : FixedText m_aRefFT;
481 : Edit m_aRefED;
482 : PushButton m_aRefBtn;
483 : FixedText m_aBindFT;
484 : ListBox m_aBindLB;
485 : FixedText m_aReplaceFT;
486 : ListBox m_aReplaceLB;
487 :
488 : FixedLine m_aButtonsFL;
489 : OKButton m_aOKBtn;
490 : CancelButton m_aEscBtn;
491 : HelpButton m_aHelpBtn;
492 :
493 : ItemNode* m_pItemNode;
494 :
495 : XFormsUIHelper1_ref m_xUIHelper;
496 : XSubmission_ref m_xNewSubmission;
497 : XPropertySet_ref m_xSubmission;
498 : XPropertySet_ref m_xTempBinding;
499 : XPropertySet_ref m_xCreatedBinding;
500 :
501 : DECL_LINK(RefHdl, void *);
502 : DECL_LINK(OKHdl, void *);
503 :
504 : void FillAllBoxes();
505 :
506 : public:
507 : AddSubmissionDialog( Window* pParent, ItemNode* _pNode,
508 : const XFormsUIHelper1_ref& _rUIHelper );
509 : ~AddSubmissionDialog();
510 :
511 0 : inline const XSubmission_ref& GetNewSubmission() const { return m_xNewSubmission; }
512 : };
513 :
514 : //========================================================================
515 : class AddModelDialog : public ModalDialog
516 : {
517 : private:
518 : FixedLine m_aModelFL;
519 : FixedText m_aNameFT;
520 : Edit m_aNameED;
521 : CheckBox m_aModifyCB;
522 : FixedLine m_aButtonsFL;
523 : OKButton m_aOKBtn;
524 : CancelButton m_aEscBtn;
525 : HelpButton m_aHelpBtn;
526 :
527 : public:
528 : AddModelDialog( Window* pParent, bool _bEdit );
529 : ~AddModelDialog();
530 :
531 0 : inline String GetName() const { return m_aNameED.GetText(); }
532 0 : inline void SetName( const String& _rName ) { m_aNameED.SetText( _rName );}
533 :
534 0 : inline bool GetModifyDoc() const { return bool( m_aModifyCB.IsChecked() ); }
535 0 : inline void SetModifyDoc( const bool _bModify ) { m_aModifyCB.Check( _bModify ); }
536 : };
537 :
538 : //========================================================================
539 : class AddInstanceDialog : public ModalDialog
540 : {
541 : private:
542 : FixedLine m_aInstanceFL;
543 : FixedText m_aNameFT;
544 : Edit m_aNameED;
545 : FixedText m_aURLFT;
546 : SvtURLBox m_aURLED;
547 : PushButton m_aFilePickerBtn;
548 : CheckBox m_aLinkInstanceCB;
549 : FixedLine m_aButtonsFL;
550 : OKButton m_aOKBtn;
551 : CancelButton m_aEscBtn;
552 : HelpButton m_aHelpBtn;
553 :
554 : String m_sAllFilterName;
555 :
556 : DECL_LINK(FilePickerHdl, void *);
557 :
558 : public:
559 : AddInstanceDialog( Window* pParent, bool _bEdit );
560 : ~AddInstanceDialog();
561 :
562 : inline void SetRenameMode();
563 0 : inline String GetName() const { return m_aNameED.GetText(); }
564 0 : inline void SetName( const String& _rName ) { m_aNameED.SetText( _rName );}
565 0 : inline String GetURL() const { return m_aURLED.GetText(); }
566 0 : inline void SetURL( const String& _rURL ) { m_aURLED.SetText( _rURL );}
567 0 : inline bool IsLinkInstance() const { return ( m_aLinkInstanceCB.IsChecked() != sal_False ); }
568 0 : inline void SetLinkInstance( bool _bLink ) { m_aLinkInstanceCB.Check( _bLink != false ); }
569 : };
570 :
571 : inline void AddInstanceDialog::SetRenameMode()
572 : {
573 : m_aURLFT.Disable();
574 : m_aURLED.Disable();
575 : m_aFilePickerBtn.Disable();
576 : m_aLinkInstanceCB.Disable();
577 : }
578 :
579 : //========================================================================
580 0 : class LinkedInstanceWarningBox : public MessBox
581 : {
582 : public:
583 : LinkedInstanceWarningBox( Window* pParent );
584 : };
585 :
586 : //............................................................................
587 : } // namespace svxform
588 : //............................................................................
589 :
590 : #endif // _SVX_DATANAVI_HXX
591 :
592 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|