text:
void ProcessTrackerAddons(const char *path, BMenu *menu);

void NewItem(BMenu *menu, BMenuItem **item, char *label, uint16 id, uint16 shortcut=0)
{
	if(shortcut) {
		*item=new BMenuItem(label, new BMessage(id), (char) shortcut);
	} else {
		*item=new BMenuItem(label, new BMessage(id));
	}
	menu->AddItem(*item);
}

SeekerWindow::SeekerWindow(SeekerApp *app, BRect frame)
 : BWindow(frame, WINDOW_TITLE, B_DOCUMENT_WINDOW, B_WILL_DRAW),
   iSplitterView(0),
   iTreeView(0),
   iFileView(0),
   iNodeMonitor(0),
   iFileWorker(0)
{
	this->iApp=app;

	// create menus
	BuildMenuBar();

	BRect bounds=this->Bounds();

	// modify bounds to accomodate menu and scrollbars
	bounds.top +=iMenuBar->Bounds().Height() + 1.0;
	iSplitterView=new CSplitterView(bounds, "SeekerWindow::SplitterView");
	AddChild(iSplitterView);

	float splitpoint;
	if(prefs->FindFloat("splitpoint",&splitpoint)!=B_OK)
		splitpoint=0.30;
	iSplitterView->SetSplitPoint(splitpoint);

	// create tree-view
	BuildTreeView();

	// create file-view
	BuildFileView();

	// add node monitor handler to our looper list
	iNodeMonitor=new SNodeMonitor(iTreeView, iFileView);
	Looper()->AddHandler(iNodeMonitor);

	// add file worker
	iFileWorker=new SFileWorker(this);

	// initial load of directories/files
	iTreeView->Refresh();

	BMessenger mountmsgr(this);
	watch_node(NULL,B_WATCH_MOUNT,mountmsgr);
}

SeekerWindow::~SeekerWindow()
{
	// save the window position and size
	prefs->RemoveData("mainframe");
	prefs->AddRect("mainframe",Frame());

	// save the placement of the divider
	prefs->RemoveData("splitpoint");
	prefs->AddFloat("splitpoint",iSplitterView->SplitPoint());

	// save the view colors
	rgb_color treecolor=iTreeView->ViewColor();;
	rgb_color filecolor=iFileView->ViewColor();;

	prefs->RemoveData("treecolor");
	prefs->AddData("treecolor",B_RGB_COLOR_TYPE,(const void *)&treecolor,sizeof(rgb_color));
	prefs->RemoveData("filecolor");
	prefs->AddData("filecolor",B_RGB_COLOR_TYPE,(const void *)&filecolor,sizeof(rgb_color));

	thread_id addon=find_thread("Seeker Tracker Addon");
	while(addon!=B_NAME_NOT_FOUND)
	{
		kill_thread(addon);
		addon=find_thread("Seeker Tracker Addon");
	}
	if(iNodeMonitor) delete iNodeMonitor;
	if(iFileWorker) delete iFileWorker;
}

void SeekerWindow::BuildMenuBar()
{

	iMenuBar=new BMenuBar(this->Bounds(), "SeekerWindow::MenuBar");

	iFileMenu=new BMenu("File");
		NewItem(iFileMenu, &iFileNewFolderItem, "New Folder", MID_FILE_NEW_FOLDER, 'N');
		iFileMenu->AddSeparatorItem();

		NewItem(iFileMenu, &iFileOpenItem, "Open", MID_FILE_OPEN, 'O');
		NewItem(iFileMenu, &iFileGetInfoItem, "Get info", MID_FILE_GET_INFO, 'I');
		NewItem(iFileMenu, &iFileEditNameItem, "Rename", MID_FILE_EDIT_NAME, 'E');
		NewItem(iFileMenu, &iFileMoveToTrashItem, "Send to Trash", MID_FILE_MOVE_TO_TRASH, 'T');
		NewItem(iFileMenu, &iFileEmptyTrashItem, "Empty trash", MID_FILE_EMPTY_TRASH);
		iFileMenu->AddSeparatorItem();

		NewItem(iFileMenu, &iFileQuitItem, "Quit", MID_FILE_QUIT, 'Q');

	iMenuBar->AddItem(iFileMenu);

	iEditMenu=new BMenu("Edit");
		NewItem(iEditMenu, &iEditCutItem, "Cut", MID_EDIT_CUT, 'X');
		NewItem(iEditMenu, &iEditCopyItem, "Copy", MID_EDIT_COPY, 'C');
		NewItem(iEditMenu, &iEditPasteItem, "Paste", MID_EDIT_PASTE, 'V');
		NewItem(iEditMenu, &iEditPasteLinkItem, "Paste link", MID_EDIT_PASTE_LINK);
		iEditMenu->AddSeparatorItem();

		NewItem(iEditMenu, &iEditSelectAllItem, "Select All", MID_EDIT_SELECT_ALL, 'A');
		NewItem(iEditMenu, &iEditSelectInvertItem, "Invert Selection", MID_EDIT_SELECT_INVERT);

	iMenuBar->AddItem(iEditMenu);

	iViewMenu=new BMenu("View");
		NewItem(iViewMenu, &iViewRefreshItem, "Refresh", MID_VIEW_REFRESH, 'R');
		iViewMenu->AddSeparatorItem();
		NewItem(iViewMenu, &iViewColumnsNameItem, "Name", MID_VIEW_COLUMNS_NAME);
		NewItem(iViewMenu, &iViewColumnsSizeItem, "Size", MID_VIEW_COLUMNS_SIZE);
		NewItem(iViewMenu, &iViewColumnsModifiedItem, "Modified", MID_VIEW_COLUMNS_MODIFIED);
		NewItem(iViewMenu, &iViewColumnsCreatedItem, "Created", MID_VIEW_COLUMNS_CREATED);
		NewItem(iViewMenu, &iViewColumnsKindItem, "Kind", MID_VIEW_COLUMNS_KIND);

	iMenuBar->AddItem(iViewMenu);

	// set initial selections
	bool tempbool;
	if(prefs->FindBool("usename",&tempbool)==B_OK && tempbool)
		iViewColumnsNameItem->SetMarked(true);
	if(prefs->FindBool("usesize",&tempbool)==B_OK && tempbool)
		iViewColumnsSizeItem->SetMarked(true);
	if(prefs->FindBool("usemodified",&tempbool)==B_OK && tempbool)
		iViewColumnsModifiedItem->SetMarked(true);
	if(prefs->FindBool("usecreated",&tempbool)==B_OK && tempbool)
		iViewColumnsCreatedItem->SetMarked(true);
	if(prefs->FindBool("usekind",&tempbool)==B_OK && tempbool)
		iViewColumnsKindItem->SetMarked(true);

	iTrackerAddonMenu=new BMenu("Addons");
	iMenuBar->AddItem(iTrackerAddonMenu);

	iHelpMenu=new BMenu("Help");
		NewItem(iHelpMenu, &iHelpAboutItem, "About...", MID_HELP_ABOUT);
	iMenuBar->AddItem(iHelpMenu);
	AddChild(iMenuBar);

	ProcessTrackerAddons("/boot/beos/system/add-ons/Tracker",iTrackerAddonMenu);
	ProcessTrackerAddons("/boot/home/config/add-ons/Tracker",iTrackerAddonMenu);

	// build popup menus
	iVolumePopUpMenu=new BPopUpMenu("Volume", false, false);
		iVolumePopUpMenu->AddSeparatorItem();
		NewItem(iVolumePopUpMenu, &iVolumePopUpOpenItem, "Open", MID_FILE_OPEN, 'O');
		NewItem(iVolumePopUpMenu, &iVolumePopUpTrackerHereItem, "Open in Tracker", MID_TRACKER_HERE);
		iVolumePopUpMenu->AddSeparatorItem();
		NewItem(iVolumePopUpMenu, &iVolumePopUpNewFolderItem, "New Folder", MID_FILE_NEW_FOLDER, 'N');
		iVolumePopUpMenu->AddSeparatorItem();
		NewItem(iVolumePopUpMenu, &iVolumePopUpEditNameItem, "Rename", MID_FILE_EDIT_NAME, 'E');
		iVolumePopUpMenu->AddSeparatorItem();
//		NewItem(iVolumePopUpMenu, &iVolumePopUpUnmountItem, "Unmount",0);
//		iVolumePopUpMenu->AddSeparatorItem();
		NewItem(iVolumePopUpMenu, &iVolumePopUpGetInfoItem, "Get Info", MID_FILE_GET_INFO, 'I');

	iFolderPopUpMenu=new BPopUpMenu("File", false, false);
		iFolderPopUpMenu->AddSeparatorItem();
		NewItem(iFolderPopUpMenu, &iFolderPopUpOpenItem, "Open", MID_FILE_OPEN, 'O');
		NewItem(iFolderPopUpMenu, &iFolderPopUpTrackerHereItem, "Open in Tracker", MID_TRACKER_HERE);
		iFolderPopUpMenu->AddSeparatorItem();
		NewItem(iFolderPopUpMenu, &iFolderPopUpNewFolderItem, "New Folder", MID_FILE_NEW_FOLDER, 'N');
		iFolderPopUpMenu->AddSeparatorItem();
		NewItem(iFolderPopUpMenu, &iFolderPopUpCutItem, "Cut", MID_EDIT_CUT, 'X');
		NewItem(iFolderPopUpMenu, &iFolderPopUpCopyItem, "Copy", MID_EDIT_COPY, 'C');
		NewItem(iFolderPopUpMenu, &iFolderPopUpPasteItem, "Paste", MID_EDIT_PASTE, 'V');
		NewItem(iFolderPopUpMenu, &iFolderPopUpPasteLinkItem, "Paste Link", MID_EDIT_PASTE_LINK);
		iFolderPopUpMenu->AddSeparatorItem();
		NewItem(iFolderPopUpMenu, &iFolderPopUpEditNameItem, "Rename", MID_FILE_EDIT_NAME, 'E');
		NewItem(iFolderPopUpMenu, &iFolderPopUpMoveToTrashItem, "Send to Trash", MID_FILE_MOVE_TO_TRASH, 'T');
		iFolderPopUpMenu->AddSeparatorItem();
		NewItem(iFolderPopUpMenu, &iFolderPopUpGetInfoItem, "Get Info", MID_FILE_GET_INFO, 'I');

	iFilePopUpMenu=new BPopUpMenu("File", false, false);
		iFilePopUpMenu->AddSeparatorItem();
		NewItem(iFilePopUpMenu, &iFilePopUpOpenItem, "Open", MID_FILE_OPEN, 'O');
		iFilePopUpMenu->AddSeparatorItem();
		NewItem(iFilePopUpMenu, &iFilePopUpCutItem, "Cut", MID_EDIT_CUT, 'X');
		NewItem(iFilePopUpMenu, &iFilePopUpCopyItem, "Copy", MID_EDIT_COPY, 'C');
		iFilePopUpMenu->AddSeparatorItem();
		NewItem(iFilePopUpMenu, &iFilePopUpEditNameItem, "Rename", MID_FILE_EDIT_NAME, 'E');
		NewItem(iFilePopUpMenu, &iFilePopUpMoveToTrashItem, "Send to Trash", MID_FILE_MOVE_TO_TRASH, 'T');
		iFilePopUpMenu->AddSeparatorItem();
		NewItem(iFilePopUpMenu, &iFilePopUpGetInfoItem, "Get Info", MID_FILE_GET_INFO, 'I');

	iTrashPopUpMenu=new BPopUpMenu("File", false, false);
		NewItem(iTrashPopUpMenu, &iTrashPopUpEmptyTrashItem, "Empty Trash", MID_FILE_EMPTY_TRASH);
		iTrashPopUpMenu->AddSeparatorItem();
		NewItem(iTrashPopUpMenu, &iTrashPopUpOpenItem, "Open", MID_FILE_OPEN, 'O');
		NewItem(iTrashPopUpMenu, &iTrashPopUpGetInfoItem, "Get Info", MID_FILE_GET_INFO, 'I');

	iDropPopUpMenu=new BPopUpMenu("Drop", false, false);
		iDropPopUpMenu->AddSeparatorItem();
		NewItem(iDropPopUpMenu, &iDropPopUpCreateLinkItem, "Create Link", MID_DROP_LINK_HERE);
		NewItem(iDropPopUpMenu, &iDropPopUpMoveItem, "Move Here", MID_DROP_MOVE_HERE);
		NewItem(iDropPopUpMenu, &iDropPopUpCopyItem, "Copy Here", MID_DROP_COPY_HERE);
		iDropPopUpMenu->AddSeparatorItem();
		NewItem(iDropPopUpMenu, &iDropPopUpCancelItem, "Cancel", B_CANCEL);
}

// create tree-view
void SeekerWindow::BuildTreeView()
{
	BRect bounds=this->Bounds();

	// a bug in the ColumnListView stuff means that we have to
	// pre-calculate the bounds of the window before creating,
	// otherwise the scrollbars don't show up
	bounds=iSplitterView->PaneFrame(C_LEFT);
	bounds.bottom -=B_H_SCROLL_BAR_HEIGHT + 4; // 4=FANCY BORDER WIDTH
	bounds.right -=B_V_SCROLL_BAR_WIDTH + 4;

	iTreeView=new STreeView(bounds, "SeekerWindow::TreeView");

	ssize_t size;
	rgb_color *color;
	if(prefs->FindData("treecolor",B_RGB_COLOR_TYPE,(const void**)&color,&size)==B_OK)
		iTreeView->SetViewColor(*color);
	iSplitterView->AddChild(iTreeView->View(), C_LEFT);
}

// create file-view
void SeekerWindow::BuildFileView()
{
	BRect bounds=this->Bounds();

	// a bug in the ColumnListView stuff means that we have to
	// pre-calculate the bounds of the window before creating,
	// otherwise the scrollbars don't show up
	bounds=iSplitterView->PaneFrame(C_RIGHT);
	bounds.bottom -=B_H_SCROLL_BAR_HEIGHT + 4; // 4=FANCY BORDER WIDTH
	bounds.right -=B_V_SCROLL_BAR_WIDTH + 4;

	iFileView=new SFileView(bounds, "SeekerWindow::FileView");

	ssize_t size;
	rgb_color *color;
	if(prefs->FindData("filecolor",B_RGB_COLOR_TYPE,(const void**)&color,&size)==B_OK)
		iFileView->SetViewColor(*color);
	iSplitterView->AddChild(iFileView->View(), C_RIGHT);
}

// toggle column selection and update file-view
void SeekerWindow::UpdateColumns(BMenuItem *item)
{
	// invert mark
	item->SetMarked(!item->IsMarked());

	// update view
	iFileView->SetColumns(iViewColumnsNameItem->IsMarked(),
						   iViewColumnsSizeItem->IsMarked(),
						   iViewColumnsModifiedItem->IsMarked(),
						   iViewColumnsCreatedItem->IsMarked(),
						   iViewColumnsKindItem->IsMarked(),
						   false);

}

// update path in window title
void SeekerWindow::UpdateTitle(BMessage *message)
{
	if(message==NULL) {
		return;
	}

	const char *path;
	if(message->FindString("path", &path) !=B_OK) {
		return;
	}

	char strg[B_PATH_NAME_LENGTH+30];
	sprintf(strg, "%s : %s", WINDOW_TITLE, path);

	SetTitle(strg);
}

// remove floating window from subset
void SeekerWindow::RemoveFromSubset(BMessage *message)
{
	if(message==NULL) {
		return;
	}

	BWindow *window;
	if(message->FindPointer("window", (void **) &window) !=B_OK) {
		return;
	}

	BWindow::RemoveFromSubset(window);
}

// current selections
void SeekerWindow::CurrentSelections(SFileList *fileList)
{
	if(iTreeView->IsFocus())
	{
		iTreeView->CurrentSelections(fileList);
	}
	else
	{
		iFileView->CurrentSelections(fileList);

		if(fileList->CountItems()==0)
		{
			// use tree-view instead
			iTreeView->CurrentSelections(fileList);
		}
	}
}

// current folder
void SeekerWindow::CurrentFolder(SFile **file, bool useSuperItem)
{
	SFileList fileList;
	iTreeView->CurrentSelections(&fileList);

	if(fileList.CountItems() > 0)
	{

		// theoretically, this list should contain one and always one item
		*file=new SFile((SFile *) fileList.ItemAt(0));

		// return parent folder ?
		// cut and copy routines have trouble using directories selected from the
		// tree-view.  In addition, this provides protection from copying the Desktop
		// root
		if(iTreeView->IsFocus())
		{

			if((*file)->IsDesktop())
			{
				delete *file;
				*file=0;
				return;
			}
			**file=*((*file)->Parent());
		}

	}
	else
		*file=0;
}

void SeekerWindow::VolumePopUp(BMessage *message)
{
	if(message==NULL)
		return;

	BPoint point;
	if(message->FindPoint("point", &point) !=B_OK)
		return;

	STreeItem *item;
	if(message->FindPointer("item", (void **) &item) !=B_OK)
		return;

	if(point.x>5)
		point.x-=5;
	if(point.y>5)
		point.y-=5;

	// Add a submenu showing the selected volume to provide extra feedback
	IconMenuItem *iconitem;

	iconitem=new IconMenuItem(item->File()->Name(),NULL, new BBitmap(item->File()->SmallIcon()));
	iVolumePopUpMenu->AddItem(iconitem,0);

	if(item->File() && (strcasecmp(item->File()->PathDesc(), "/boot")==0))
	{
		iVolumePopUpEditNameItem->SetEnabled(false);
//		iVolumePopUpUnmountItem->SetEnabled(false);
	}
	BMenuItem *result=iVolumePopUpMenu->Go(point,false,true);

	iVolumePopUpMenu->RemoveItem(iconitem);
	delete iconitem;

	uint32 msgId=0;

	if(result==iVolumePopUpOpenItem)
		msgId=MID_FILE_OPEN;
	else if(result==iVolumePopUpNewFolderItem)
		msgId=MID_FILE_NEW_FOLDER;
	else if(result==iVolumePopUpGetInfoItem)
		msgId=MID_FILE_GET_INFO;
	else if(result==iVolumePopUpEditNameItem)
		msgId=MID_FILE_EDIT_NAME;
	else if(result==iVolumePopUpTrackerHereItem)
		msgId=MID_TRACKER_HERE;
	else if(result==iVolumePopUpUnmountItem)
	{
		item->RequestScanTerminate();
		fs_unmount_volume(item->File()->PathDesc(), 0);
	}

	if(!iVolumePopUpEditNameItem->IsEnabled())
	{
		iVolumePopUpEditNameItem->SetEnabled(true);
//		iVolumePopUpUnmountItem->SetEnabled(true);
	}

	if(msgId)
	{
		BMessage message(msgId);
		message.AddInt8("fileview",0);
		Looper()->PostMessage(&message);
	}

}

void SeekerWindow::FolderPopUp(BMessage *message)
{
	if(message==NULL)
	{
		printf("FolderPopUp(NULL)\n");
		return;
	}

	BPoint point;
	if(message->FindPoint("point", &point)!=B_OK)
	{
		printf("FolderPopUp: Couldn't find point\n");
		return;
	}

	int8 fileview;
	if(message->FindInt8("fileview", &fileview)!=B_OK)
	{
		printf("FolderPopUp: Couldn't find fileview flag\n");
		fileview=0;
	}

	SeekerItem *item;
	if(message->FindPointer("item", (void **) &item)!=B_OK)
	{
		printf("FolderPopUp: Couldn't find item\n");
		return;
	}

	if(point.x>5)
		point.x-=5;
	if(point.y>5)
		point.y-=5;

	// Get the file list
	SFileList *filelist=new SFileList;
	CurrentSelections(filelist);

	// Add a submenu showing all the selected files to provide extra feedback
	BMenu *menu=NULL;
	IconMenuItem *iconitem=NULL;

	if(filelist->CountItems()==0)
	{
		delete filelist;
		return;
	}

	// Just create 1 menu item if there is only one file selected
	if(filelist->CountItems()==1)
	{
		SFile *f=(SFile*)filelist->ItemAt(0);
		iconitem=new IconMenuItem(f->Name(),NULL, new BBitmap(f->SmallIcon()));
		iFolderPopUpMenu->AddItem(iconitem,0);
	}
	else
	{
		// Function adds multiple selections to the menu
		menu=GenerateIconMenu(filelist);
		iFolderPopUpMenu->AddItem(menu,0);
	}

	// Disable certain things you just don't do to certain items, such as /boot,
	// the Trash, or the Desktop
	bool disabled_items=false;
	for(int32 i=0;i<filelist->CountItems();i++)
	{
		SFile *f=(SFile*)filelist->ItemAt(i);
		if(f && f->IsSystem())
		{
			iFolderPopUpEditNameItem->SetEnabled(false);
			iFolderPopUpMoveToTrashItem->SetEnabled(false);
			iFolderPopUpCutItem->SetEnabled(false);
			disabled_items=true;
			break;
		}
	}

	BMenuItem *result=iFolderPopUpMenu->Go(point,true,true);

	if(disabled_items)
	{
		iFolderPopUpEditNameItem->SetEnabled(true);
		iFolderPopUpMoveToTrashItem->SetEnabled(true);
		iFolderPopUpCutItem->SetEnabled(true);
	}

	// Remove all the iconized selection-related menu items from the popup menu
	if(filelist->CountItems()==1)
	{
		iFolderPopUpMenu->RemoveItem(iconitem);
		delete iconitem;
	}
	else
	{
		iFolderPopUpMenu->RemoveItem(menu);
		delete menu;
	}

	uint32 msgId=0;

	if(result==iFolderPopUpOpenItem) {
		msgId=MID_FILE_OPEN;
	} else if(result==iFolderPopUpNewFolderItem) {
		msgId=MID_FILE_NEW_FOLDER;
	} else if(result==iFolderPopUpGetInfoItem) {
		msgId=MID_FILE_GET_INFO;
	} else if(result==iFolderPopUpEditNameItem) {
		msgId=MID_FILE_EDIT_NAME;
	} else if(result==iFolderPopUpMoveToTrashItem) {
		msgId=MID_FILE_MOVE_TO_TRASH;
	} else if(result==iFolderPopUpCutItem) {
		msgId=MID_EDIT_CUT;
	} else if(result==iFolderPopUpCopyItem) {
		msgId=MID_EDIT_COPY;
	} else if(result==iFolderPopUpPasteItem) {
		msgId=MID_EDIT_PASTE;
	} else if(result==iFolderPopUpPasteLinkItem) {
		msgId=MID_EDIT_PASTE_LINK;
	} else if(result==iFolderPopUpTrackerHereItem)
		msgId=MID_TRACKER_HERE;

	if(msgId)
	{
		BMessage message(msgId);
		message.AddInt8("fileview",fileview);
		Looper()->PostMessage(&message);
	}

	filelist->MakeEmpty();
	delete filelist;
}

void SeekerWindow::FilePopUp(BMessage *message)
{
	if(message==NULL)
		return;

	BPoint point;
	if(message->FindPoint("point", &point) !=B_OK)
		return;

	STreeItem *item;
	if(message->FindPointer("item", (void **) &item) !=B_OK)
		return;

	if(point.x>5)
		point.x-=5;
	if(point.y>5)
		point.y-=5;

	// Get the file list
	SFileList *filelist=new SFileList;
	CurrentSelections(filelist);

	// Add a submenu showing all the selected files to provide extra feedback
	BMenu *menu=NULL;
	IconMenuItem *iconitem=NULL;

	if(filelist->CountItems()==0)
	{
		delete filelist;
		return;
	}

	// Just create 1 menu item if there is only one file selected
	if(filelist->CountItems()==1)
	{
		iconitem=new IconMenuItem(item->File()->Name(),NULL, new BBitmap(item->File()->SmallIcon()));
		iFilePopUpMenu->AddItem(iconitem,0);
	}
	else
	{
		// Function adds multiple selections to the menu
		menu=GenerateIconMenu(filelist);
		iFilePopUpMenu->AddItem(menu,0);
	}

	BMenuItem *result=iFilePopUpMenu->Go(point, true);

	// Remove all the iconized selection-related menu items from the popup menu
	if(filelist->CountItems()==1)
	{
		iFilePopUpMenu->RemoveItem(iconitem);
		delete iconitem;
	}
	else
	{
		iFilePopUpMenu->RemoveItem(menu);
		delete menu;
	}

	uint32 msgId=0;

	if(result==iFilePopUpOpenItem) {
		msgId=MID_FILE_OPEN;
	} else if(result==iFilePopUpGetInfoItem) {
		msgId=MID_FILE_GET_INFO;
	} else if(result==iFilePopUpEditNameItem) {
		msgId=MID_FILE_EDIT_NAME;
	} else if(result==iFilePopUpMoveToTrashItem) {
		msgId=MID_FILE_MOVE_TO_TRASH;
	} else if(result==iFilePopUpCutItem) {
		msgId=MID_EDIT_CUT;
	} else if(result==iFilePopUpCopyItem) {
		msgId=MID_EDIT_COPY;
	}

	if(msgId)
	{
		BMessage message(msgId);
		Looper()->PostMessage(&message);
	}
}

void SeekerWindow::TrashPopUp(BMessage *message)
{
	if(message==NULL)
		return;

	BPoint point;
	if(message->FindPoint("point", &point) !=B_OK)
		return;

	STreeItem *item;
	if(message->FindPointer("item", (void **) &item) !=B_OK)
		return;

	if(point.x>5)
		point.x-=5;
	if(point.y>5)
		point.y-=5;
	BMenuItem *result=iTrashPopUpMenu->Go(point,false,true);

	uint32 msgId=0;

	if(result==iTrashPopUpOpenItem) {
		msgId=MID_FILE_OPEN;
	} else if(result==iTrashPopUpGetInfoItem) {
		msgId=MID_FILE_GET_INFO;
	} else if(result==iTrashPopUpEmptyTrashItem) {
		msgId=MID_FILE_EMPTY_TRASH;
	}

	if(msgId)
	{
		BMessage message(msgId);
		Looper()->PostMessage(&message);
	}

}

void SeekerWindow::DropPopUp(BMessage *message)
{
	if(message==NULL)
	{
		printf("NULL Drop message\n");
		return;
	}

	BPoint point,screenpoint, menupoint;
	if(message->FindPoint("_drop_point_", &screenpoint) !=B_OK)
		return;

	point=ConvertFromScreen(screenpoint);

	// figure out which pane received the drop and get the appropriate list item
	int8 treeview=0;	// 0=neither pane, 1=treeview, 2=fileview

	if(iTreeView->Parent()->Frame().Contains(point))
		treeview=1;
	else
		if(iFileView->Parent()->Frame().Contains(point))
			treeview=2;

	if(treeview==0)
		return;

	// Add color drop support to the app
	rgb_color *dropcolor;
	ssize_t size;
	if (message->FindData("RGBColor", 'RGBC',(const void**)&dropcolor, &size) == B_OK)
	{
		if(treeview==1)
			iTreeView->SetViewColor(*dropcolor);
		else
			iFileView->SetViewColor(*dropcolor);
	}

	// Get the target item in the tree. This can be any kind of item - if there is
	// one at all. It is possible to drop it in the right pane on nothing
	SFile *dropfile=NULL;
	SeekerItem *dropitem;
	int32 itemindex=0;
	if(treeview==1)
	{
		itemindex=iTreeView->IndexOf(iTreeView->ConvertFromScreen(screenpoint));
		if(itemindex>=0)
		{
			dropitem=(SeekerItem*)iTreeView->ItemAt(itemindex);
			dropfile=dropitem->File();
		}
		else
		{
			// well, it was just plain dropped in a blank area. See if there
			// is a selected folder. If so, copy to that folder. If not,
			// use the fileview's current path. If there isn't one, there
			// are *serious* problems going on here and we need to just
			// do nothing.
			STreeItem *dropitem=(STreeItem*)iTreeView->ItemAt(iTreeView->CurrentSelection());
			if(dropitem)
				dropfile=dropitem->File();
			else
			{
				dropfile=iFileView->PathAsFile();
				if(!dropfile)
					return;
			}
		}
	}
	else
	{
		itemindex=iFileView->IndexOf(iFileView->ConvertFromScreen(screenpoint));
		if(itemindex>=0)
		{
			dropitem=(SeekerItem*)iFileView->ItemAt(itemindex);
			dropfile=dropitem->File();
		}
		else
		{
			dropfile=iFileView->PathAsFile();
		}
	}

	// Determine whether we need to pop up a menu. If a drop is made on a file,
	// we need to launch the targeted application if an application or a symlink
	// to one, or we do nothing and if otherwise.

	// treeview == 2 when dropped on the iFileView
	if(treeview==2 && dropfile->TargetType()==TYPE_FILE)
	{
		// MimeDesc() is passed True, it returns the type of the target
		// if it's a link or its own type if not a link
		BString mimestr(dropfile->MimeDesc(true));

		if(mimestr.Compare("application/x-vnd.Be-elfexecutable")==0 ||
			mimestr.Compare("Be Application")==0)
		{
			// an executable, if launched without argv/argc expects a B_REFS_RECEIVED
			// message. Seeing how it only has the attachment "refs", we can get away
			// with changing the command constant and sending it to Launch()
			message->what=B_REFS_RECEIVED;
			be_roster->Launch(dropfile->Ref(),message);
			return;
		}
		return;
	}

	// we got this far, so the drop target is evidently a folder or a link to one.
	// Check to see if it's the Trash. If it is, automatically do a MoveToTrash.
	// Otherwise, pop up the menu and get the appropriate command

	// Set up the file list for the file operations
	SFileList *filelist=new SFileList(0);
	entry_ref ref;
	int32 refindex=0;
	SFile *fileitem;

	while(message->FindRef("refs",refindex,&ref)==B_OK)
	{
		refindex++;
		fileitem=new SFile(&ref);
		filelist->AddItem(fileitem);
	}

	bool usetrash=(dropfile->IsTrash())?true:false;
	BMenuItem *result=NULL;

	if(usetrash==false)
	{
		// Add a submenu showing all the selected files to provide extra feedback
		BMenu *menu=NULL;
		IconMenuItem *iconitem=NULL;

		// Just create 1 menu item if there is only one file selected
		if(filelist->CountItems()==1)
		{
			SFile *f=(SFile*)filelist->ItemAt(0);
			iconitem=new IconMenuItem(f->Name(),NULL, new BBitmap(f->SmallIcon()));
			iDropPopUpMenu->AddItem(iconitem,0);
		}
		else
		{
			// Function adds multiple selections to the menu
			menu=GenerateIconMenu(filelist);
			if(menu)
				iDropPopUpMenu->AddItem(menu,0);
		}

		// Disable certain things you just don't do to certain items, such as /boot,
		// the Trash, or the Desktop
		bool disabled_items=false;
		for(int32 i=0;i<filelist->CountItems();i++)
		{
			SFile *f=(SFile*)filelist->ItemAt(i);
			if(f && f->IsSystem())
			{
				iDropPopUpMoveItem->SetEnabled(false);
				disabled_items=true;
				break;
			}
		}

		menupoint=screenpoint;
		if(menupoint.x>5)
			menupoint.x-=5;
		if(menupoint.y>5)
			menupoint.y-=5;
		result=iDropPopUpMenu->Go(menupoint,false,true);

		if(disabled_items)
			iDropPopUpMoveItem->SetEnabled(false);

		// Remove all the iconized selection-related menu items from the popup menu
		if(filelist->CountItems()==1)
		{
			iDropPopUpMenu->RemoveItem(iconitem);
			delete iconitem;
		}
		else
		{
			if(menu)
			{
				iDropPopUpMenu->RemoveItem(menu);
				delete menu;
			}
		}
	}

	if(usetrash)
		iFileWorker->MoveFiles(filelist,dropfile);
	else
		if(result==iDropPopUpCreateLinkItem)
			iFileWorker->MakeLinks(filelist,dropfile);
		else
			if(result==iDropPopUpMoveItem)
				iFileWorker->MoveFiles(filelist,dropfile);
			else
				if(result==iDropPopUpCopyItem)
					iFileWorker->CopyFiles(filelist,dropfile);
				else
					return;

	// Clean up our mess
	SFile *removedfile;
	for(int32 i=0;i<filelist->CountItems();i++)
	{
		removedfile=(SFile*)filelist->ItemAt(i);
		delete removedfile;
	}
	filelist->MakeEmpty();
	delete filelist;
}

bool SeekerWindow::QuitRequested()
{
	iTreeView->AbortScan();
	be_app->PostMessage(B_QUIT_REQUESTED);
	return true;
}

void SeekerWindow::MessageReceived(BMessage* message)
{
	SFile *currentFolder=0;
	SFileList fileList;

	switch(message->what)
	{
		case MID_FILE_NEW_FOLDER:
		{
			CurrentSelections(&fileList);
			if(fileList.CountItems()==1)
			{
				SFile *file=(SFile *)fileList.ItemAt(0);
				if(file && file->TargetType()==TYPE_DIRECTORY)
					iFileWorker->NewFolder(file);
			}
			else
			if(fileList.CountItems()>1)
			{
				// we have multiple files, so get the parent folder from
				// one of the entries
				SFile *file=(SFile *)fileList.ItemAt(0);
				if(file)
					iFileWorker->NewFolder(file->Parent());
			}
			break;
		}
  		case MID_FILE_OPEN:
  		{
			if(iFileView->IsFocus())
				iFileView->Open();

			if(iTreeView->IsFocus())
			{
				STreeItem *item=(STreeItem *) iTreeView->ItemAt(iTreeView->CurrentSelection());
				if(item)
					iTreeView->Expand(item);
			}
  			break;
  		}
  		case MID_FILE_GET_INFO:
  		{
			CurrentSelections(&fileList);
			iFileWorker->GetInfo(&fileList);
			break;
		}
		case MID_FILE_EDIT_NAME:
		{
			CurrentSelections(&fileList);
			iFileWorker->EditName(&fileList);
			break;
		}
		case MID_FILE_MOVE_TO_TRASH:
		{
			CurrentSelections(&fileList);
			CurrentFolder(&currentFolder, true);
			if(currentFolder)
				iFileWorker->MoveToTrash(currentFolder, &fileList);
			break;
		}
		case MID_FILE_EMPTY_TRASH:
		{
			iFileWorker->EmptyTrash();
			break;
		}
 		case MID_FILE_QUIT:
 		{
			Quit();
  			break;
		}
		case MID_EDIT_CUT:
		{
			CurrentSelections(&fileList);
			CurrentFolder(&currentFolder, true);
			if(currentFolder)
				iFileWorker->Cut(currentFolder, &fileList);
			break;
		}
		case MID_EDIT_COPY:
		{
			CurrentSelections(&fileList);
			CurrentFolder(&currentFolder, true);
			if(currentFolder)
				iFileWorker->Copy(currentFolder, &fileList);
			break;
		}
		case MID_EDIT_PASTE:
		{
			CurrentSelections(&fileList);
			if(fileList.CountItems() > 0)
				iFileWorker->Paste((SFile *) fileList.ItemAt(fileList.CountItems()-1));
			break;
		}
		case MID_EDIT_PASTE_LINK:
		{
			CurrentSelections(&fileList);
			if(fileList.CountItems() > 0)
				iFileWorker->PasteLink((SFile *) fileList.ItemAt(fileList.CountItems()-1));
			break;
		}
		case MID_EDIT_SELECT_ALL:
		{
			iFileView->SelectAll();
			break;
		}
		case MID_EDIT_SELECT_INVERT:
		{
			iFileView->InvertSelection();
			break;
		}
  		case MID_VIEW_COLUMNS_NAME :
		{
			UpdateColumns(iViewColumnsNameItem);
			break;
		}
  		case MID_VIEW_COLUMNS_SIZE :
		{
			UpdateColumns(iViewColumnsSizeItem);
			break;
		}
		case MID_VIEW_COLUMNS_MODIFIED:
		{
			UpdateColumns(iViewColumnsModifiedItem);
			break;
		}
		case MID_VIEW_COLUMNS_CREATED:
		{
			UpdateColumns(iViewColumnsCreatedItem);
			break;
		}
		case MID_VIEW_COLUMNS_KIND:
		{
			UpdateColumns(iViewColumnsKindItem);
			break;
		}
  		case MID_VIEW_REFRESH:
		{
  			iTreeView->Refresh();
  			break;
		}
		case MID_TRACKER_HERE:
		{
			int8 fileview;
			if(message->FindInt8("fileview",&fileview)==B_OK)
			{
				if(fileview)
					iFileView->SpawnTracker();
				else
					iTreeView->SpawnTracker();
			}
			break;
		}
		case MID_TRACKER_ADDON:
		{
			image_id id;
			if(message->FindInt32("addon",&id)==B_OK)
				RunTrackerAddon(id);
			break;
		}
  		case MSG_PIONEER_UPDATE_TITLE:
		{
  			UpdateTitle(message);
  			break;
		}
  		case MSG_PIONEER_REMOVE_FROM_SUBSET :
		{
  			RemoveFromSubset(message);
  			break;
		}
  		case MSG_PIONEER_VOLUME_POPUP_MENU :
		{
  			VolumePopUp(message);
  			break;
		}
		case MSG_PIONEER_FOLDER_POPUP_MENU:
		{
			FolderPopUp(message);
			break;
		}
  		case MSG_PIONEER_FILE_POPUP_MENU:
		{
  			FilePopUp(message);
  			break;
		}
  		case MSG_PIONEER_TRASH_POPUP_MENU:
		{
  			TrashPopUp(message);
  			break;
		}
  		case MSG_TREEVIEW_EXPAND:
		{
  			iTreeView->ExpandAndSelect(message);
  			break;
		}
  		case MSG_FILEVIEW_REFRESH:
		{
 			iFileView->Refresh(message);
  			break;
		}
  		case MSG_FILEVIEW_REFRESH_CURRENT:
		{
 			iFileView->Refresh();
  			break;
		}
  		case MSG_FILEVIEW_INVOKE:
		{
  			iFileView->Open();
  			break;
		}
  		case MSG_FILEVIEW_CLEAR:
		{
  			iFileView->Clear();
  			break;
		}
  		case MSG_NODEMONITOR_ADD_WATCH:
		{
  			iNodeMonitor->AddWatch(message);
  			break;
		}
  		case MSG_NODEMONITOR_REMOVE_WATCH :
		{
  			iNodeMonitor->RemoveWatch(message);
  			break;
		}
		case B_PASTE:
		{
			if(message->WasDropped())
			{
				// Add color drop support to the app
				rgb_color *dropcolor;
				ssize_t size;
				if(message->FindData("RGBColor", 'RGBC',(const void**)&dropcolor, &size)!=B_OK)
					break;

				BPoint screenpoint;
				if(message->FindPoint("_drop_point_", &screenpoint) !=B_OK)
					break;

				ConvertFromScreen(&screenpoint);

				if(iTreeView->Parent()->Frame().Contains(screenpoint))
				{
					iTreeView->SetViewColor(*dropcolor);
					iTreeView->Invalidate();
				}
				else
					if(iFileView->Parent()->Frame().Contains(screenpoint))
					{
						iFileView->SetViewColor(*dropcolor);
						iFileView->Invalidate();
					}
			}
			break;
		}
		case B_SIMPLE_DATA:
		{
			if(message->WasDropped())
				DropPopUp(message);
			break;
		}
		case B_REFS_RECEIVED:
		{
			entry_ref ref;
			if(message->FindRef("refs",0,&ref)==B_OK)
			{
				BEntry entry(&ref);
				if(!entry.IsDirectory())
				{
					BEntry parent;
					entry.GetParent(&parent);
					parent.GetRef(&ref);
				}
				iTreeView->ExpandAndSelect(ref);
			}
			break;
		}
		case MID_HELP_ABOUT:
			be_app->PostMessage(new BMessage(B_ABOUT_REQUESTED));
			break;
		default:
			BWindow::MessageReceived(message);
	}
}

void SeekerWindow::RefreshTrackerAddons(void)
{
	// empty tracker addon menu
	BMenuItem *mitem=iTrackerAddonMenu->RemoveItem((int32)0);
	while(mitem)
	{
		delete mitem;
		mitem=iTrackerAddonMenu->RemoveItem((int32)0);
	}

	// iterate through /boot/beos/system/addons/Tracker
	// and ~config/addons/Tracker, adding only legit addons
}

void ProcessTrackerAddons(const char *path, BMenu *menu)
{
	if(!path || !menu)
		return;

	BDirectory *dir=new BDirectory(path);
	BEntry entry;
	BNode node;
	BNodeInfo nodeinfo;
	BPath epath;
	BString string;
	BMenuItem *item;
	addon_process_refs *processfunc=NULL;
	status_t stat;
	image_id addon;
	BMessage *addonmsg;

	while(dir->GetNextEntry(&entry)==B_OK)
	{
		entry.GetPath(&epath);
		addon=load_add_on(epath.Path());
		stat=get_image_symbol(addon, "process_refs", B_SYMBOL_TYPE_TEXT, (void**)&processfunc);

		if(stat!=B_OK)
		{
			printf("ERROR: file %s is not a Tracker Addon\n", epath.Path());
			unload_add_on(addon);
			continue;
		}

		// if we got this far, it must be a tracker addon, so add the thing to the
		// menu

		string.SetTo(epath.Path());

		// obtain just the file's leaf
		string.Remove(0,string.FindLast('/')+1);

		// remove the trailing shortcut from the name string, if there is one.
		int32 dashpos=string.FindLast('-');
		uint8 shortcut=(uint8)string.ByteAt(string.CountChars()-1);

		addonmsg=new BMessage(MID_TRACKER_ADDON);
		addonmsg->AddInt32("addon",addon);

		// Set up to get the icon
		node.SetTo(&entry);
		nodeinfo.SetTo(&node);

		// We have to jump through a lot of hoops to determine the keyboard
		// shortcut because the kind of format is specific, but we don't want
		// to truncate the name of any addon which uses a dash and doesn't fit
		// the shortcut format
		if(dashpos!=B_ERROR && dashpos==string.CountChars()-2 &&
			( (shortcut>64 && shortcut<91) || (shortcut>96 && shortcut<123)) )
		{
			string.Truncate(dashpos);

			// This sucker will have the same exact keyboard shortcut as Tracker. :)
			item=new BMenuItem(string.String(),addonmsg,(char)shortcut,
				B_COMMAND_KEY | B_OPTION_KEY);

			// Need a little more work before I can import the OpenTracker IconMenuItem stuff
//			item=(BMenuItem*)new IconMenuItem(string.String(),addonmsg,&nodeinfo,
//				B_MINI_ICON);
		}
		else
		{
			item=new BMenuItem(string.String(),addonmsg);
		}
		menu->AddItem(item);
	}

	delete dir;
}

void SeekerWindow::RunTrackerAddon(image_id addon)
{
	// get the working directory item
	STreeItem *treeitem=(STreeItem*)iTreeView->ItemAt(iTreeView->CurrentSelection());
	if(!treeitem)
		return;

	// Create the ref message based on which pane is active
	BMessage *refmsg=new BMessage(B_REFS_RECEIVED);
	if(iTreeView->IsFocus())
		refmsg->AddRef("refs",treeitem->File()->Ref());
	else
	{
		if(iFileView->IsFocus())
		{
			SFileList *list=new SFileList(0);
			iFileView->CurrentSelections(list);
			SFile*file;

			for(int32 i=0; i<list->CountItems();i++)
			{
				file=(SFile*)list->ItemAt(i);
				if(file)
					refmsg->AddRef("refs",file->Ref());
			}
			list->MakeEmpty();
			delete list;

		}
		else
		{
			delete refmsg;
			return;
		}
	}
	refmsg->AddRef("directory",treeitem->File()->Ref());
	refmsg->AddInt32("addon",addon);

	thread_id addon_thread=spawn_thread(TrackerAddonThread,"Seeker Tracker Addon",
		B_NORMAL_PRIORITY,refmsg);

	if(addon_thread!=B_NO_MORE_THREADS && addon_thread!=B_NO_MEMORY)
		resume_thread(addon_thread);
	else
		delete refmsg;

	// Don't need to delete the thing because the addon thread will do it
	//delete refmsg;
}

int32 SeekerWindow::TrackerAddonThread(void *data)
{
	BMessage *msg=(BMessage*)data;
	image_id addon;
	entry_ref ref;

	if(msg->FindInt32("addon",&addon)!=B_OK)
	{
		delete msg;
		return -1;
	}

	if(msg->FindRef("directory",&ref)!=B_OK)
	{
		delete msg;
		return -1;
	}

	// Initial setup
	addon_process_refs *processfunc=NULL;

	status_t status;
	status=get_image_symbol(addon, "process_refs", B_SYMBOL_TYPE_TEXT, (void**)&processfunc);

	if(status!=B_OK)
	{
		delete msg;
		return -1;
	}

	// we make a dummy pointer in case some addon would choke if we just passed NULL
	int8 *ptr=NULL;

	processfunc(ref,msg,ptr);

	return 0;
}

BMenu *GenerateIconMenu(const SFileList *filelist)
{
	int32 filecount=filelist->CountItems();
	if(filecount==0)
		return NULL;

	IconMenuItem *iconitem;
	SFile *file;

	BMenu *menu=new BMenu("Files");

	for(int32 i=0; i<filecount;i++)
	{
		file=(SFile*)filelist->ItemAt(i);
		if(file)
		{
			iconitem=new IconMenuItem(file->Name(),NULL,new BBitmap(file->SmallIcon()));
			menu->AddItem(iconitem);
		}
	}
	return menu;
}

void SeekerWindow::WindowActivated(bool active)
{
	if(!active)
	{
		if(iFileView->IsTracking())
			iFileView->EndTracking();
	}
}

void SeekerWindow::FrameMoved(BPoint origin)
{
	prefs->RemoveData("mainframe");
	prefs->AddRect("mainframe",Frame());
}

void SeekerWindow::FrameResized(float width, float height)
{
	prefs->RemoveData("mainframe");
	prefs->AddRect("mainframe",Frame());
}


text:
package com.clover_studio.spikachatmodule.adapters;

import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.clover_studio.spikachatmodule.R;
import com.clover_studio.spikachatmodule.lazy.ImageLoaderSpice;
import com.clover_studio.spikachatmodule.models.Message;
import com.clover_studio.spikachatmodule.models.User;
import com.clover_studio.spikachatmodule.utils.Const;
import com.clover_studio.spikachatmodule.utils.MessageSortByCreated;
import com.clover_studio.spikachatmodule.utils.Tools;
import com.clover_studio.spikachatmodule.utils.VCardParser;

import java.util.Collections;
import java.util.List;

/**
 * Created by ubuntu_ivo on 17.07.15..
 */
public class MessageRecyclerViewAdapter extends RecyclerView.Adapter<MessageRecyclerViewAdapter.ViewHolder>{

    private List<Message> data;
    private User myUser;
    private OnLastItemAndOnClickListener lastItemListener;

    public MessageRecyclerViewAdapter (List<Message> data, User myUser){
        this.data = data;
        this.myUser = myUser;
    }

    /**
     * add sent message to adapter
     *
     * @param message sent message
     */
    public void addSentMessage(Message message){
        message.user = myUser;

        data.add(message);
        notifyDataSetChanged();
    }

    /**
     *  add received message to adapter
     *
     * @param message received message
     */
    public void addReceivedMessage(Message message){
        data.add(message);
        notifyDataSetChanged();
    }

    /**
     * replaced delivered message with sent message
     *
     * @param message delivered message
     */
    public void setDeliveredMessage(Message message){
        for(Message item : data){
            if(item.localID != null && item.localID.equals(message.localID)){
                item.status = Const.MessageStatus.DELIVERED;
                item._id = message._id;
                item.created = message.created;
                item.timestampFormatted = "";
                break;
            }
        }
        notifyDataSetChanged();
    }

    /**
     * add messages to adapter
     *
     * @param data messages to add
     */
    public void addMessages (List<Message> data){
        this.data.addAll(data);
        Collections.sort(this.data, new MessageSortByCreated());
        notifyDataSetChanged();
    }

    /**
     * update messages with new given messages
     *
     * @param messagesForUpdate message for update
     */
    public void updateMessages (List<Message> messagesForUpdate){
        for(Message item : data){
            for(Message itemNew : messagesForUpdate){
                if(item._id != null && item._id.equals(itemNew._id)){
                    item.copyMessage(itemNew);
                    continue;
                }
            }
        }
        notifyDataSetChanged();
    }

    public void clearMessages(){
        data.clear();
        notifyDataSetChanged();
    }

    /**
     * set on last item visible and on click listener
     *
     * @param listener
     */
    public void setLastItemListener(OnLastItemAndOnClickListener listener){
        lastItemListener = listener;
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        View parentView;

        //my views
        TextView myMessage;
        RelativeLayout myRelative;
        View myMessageStatus;
        ImageView myAvatar;
        ImageView myInfoImage;
        ImageView myImage;
        RelativeLayout myImageLayout;
        RelativeLayout myFile;
        TextView myNameAndTime;

        //you views
        TextView youMessage;
        RelativeLayout youRelative;
        ImageView youAvatar;
        ImageView youInfoImage;
        ImageView youImage;
        RelativeLayout youImageLayout;
        RelativeLayout youFile;
        TextView youNameAndTime;

        ViewHolder(View v) {
            super(v);

            parentView = v.findViewById(R.id.parentView);

            myMessage = (TextView) v.findViewById(R.id.myMessage);
            myRelative = (RelativeLayout) v.findViewById(R.id.myRelativeLayout);
            myMessageStatus = v.findViewById(R.id.myMessageStatus);
            myAvatar = (ImageView) v.findViewById(R.id.myAvatar);
            myImageLayout = (RelativeLayout) v.findViewById(R.id.myImageLayout);
            myImage = (ImageView) v.findViewById(R.id.myImage);
            myInfoImage = (ImageView) v.findViewById(R.id.myImageInfo);
            myFile = (RelativeLayout) v.findViewById(R.id.myFile);
            myNameAndTime = (TextView) v.findViewById(R.id.myNameAndTime);

            youMessage = (TextView) v.findViewById(R.id.youMessage);
            youRelative = (RelativeLayout) v.findViewById(R.id.youRelativeLayout);
            youAvatar = (ImageView) v.findViewById(R.id.youAvatar);
            youImageLayout = (RelativeLayout) v.findViewById(R.id.youImageLayout);
            youImage = (ImageView) v.findViewById(R.id.youImage);
            youInfoImage = (ImageView) v.findViewById(R.id.youImageInfo);
            youFile = (RelativeLayout) v.findViewById(R.id.youFile);
            youNameAndTime = (TextView) v.findViewById(R.id.youNameAndTime);

        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false));
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        final Message message = data.get(position);

        //set images to null and hide views
        holder.myAvatar.setImageDrawable(null);
        holder.myImage.setImageDrawable(null);
        holder.youAvatar.setImageDrawable(null);

        holder.myImageLayout.setVisibility(View.GONE);
        holder.youImageLayout.setVisibility(View.GONE);
        holder.myFile.setVisibility(View.GONE);
        holder.youFile.setVisibility(View.GONE);
        holder.myMessage.setVisibility(View.GONE);
        holder.youMessage.setVisibility(View.GONE);
        //*******************************

        TextView messageTV = null;
        ImageView imageIV = null;
        RelativeLayout imageLayout = null;
        ImageView info = null;
        RelativeLayout fileRL = null;

        boolean isMyMessage = isMessageFromUser(message, myUser);

        if(isMyMessage){
            holder.myRelative.setVisibility(View.VISIBLE);
            holder.youRelative.setVisibility(View.GONE);

            messageTV = holder.myMessage;
            imageIV = holder.myImage;
            imageLayout = holder.myImageLayout;
            fileRL = holder.myFile;
        }else{
            holder.myRelative.setVisibility(View.GONE);
            holder.youRelative.setVisibility(View.VISIBLE);

            messageTV = holder.youMessage;
            imageIV = holder.youImage;
            imageLayout = holder.youImageLayout;
            fileRL = holder.youFile;
        }

        if(message.deleted != -1 && message.deleted != 0){
            messageTV.setVisibility(View.VISIBLE);
            messageTV.setText(messageTV.getContext().getString(R.string.message_deleted_at) + " " + Tools.generateDate(Const.DateFormats.USER_JOINED_DATE_FORMAT, message.deleted));
        }else if(message.type == Const.MessageType.TYPE_TEXT){

            messageTV.setVisibility(View.VISIBLE);
            messageTV.setText(message.message);

        }else if(message.type == Const.MessageType.TYPE_NEW_USER){

            messageTV.setVisibility(View.VISIBLE);
            messageTV.setText(message.user.name + " " + messageTV.getContext().getString(R.string.joined_to_conversation));

        }else if(message.type == Const.MessageType.TYPE_USER_LEAVE){

            messageTV.setVisibility(View.VISIBLE);
            messageTV.setText(message.user.name + " " + messageTV.getContext().getString(R.string.left_from_conversation));

        }else if(message.type == Const.MessageType.TYPE_FILE){

            //if is image
            if(Tools.isMimeTypeImage(message.file.file.mimeType)){
                imageLayout.setVisibility(View.VISIBLE);
                ImageLoaderSpice.getInstance(imageIV.getContext()).displayImage(imageIV, Tools.getFileUrlFromId(message.file.thumb.id), 0);

                if(isMyMessage){
                    info = holder.myInfoImage;
                }else{
                    info = holder.youInfoImage;
                }

            }else{
                fileRL.setVisibility(View.VISIBLE);
                showAllChildrenFromLayout(fileRL);

                if(isMyMessage){
                    info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
                }else{
                    info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
                }

                ((TextView)fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_NAME)).setText(message.file.file.name);
                ((TextView)fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_SIZE)).setText(Tools.readableFileSize(Long.valueOf(message.file.file.size)));
                ((TextView)fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_DOWNLOAD)).setText(fileRL.getContext().getResources().getString(R.string.download));

                int drawable = 0;
                if(Tools.isMimeTypeVideo(message.file.file.mimeType)){

                    if(isMyMessage){
                        drawable = R.drawable.ic_video_label_white;
                    }else{
                        drawable = R.drawable.ic_video_label;
                    }
                }else if(Tools.isMimeTypeAudio(message.file.file.mimeType)){

                    if(isMyMessage){
                        drawable = R.drawable.ic_audio_label_white;
                    }else{
                        drawable = R.drawable.ic_audio_label;
                    }
                }else{

                    if(isMyMessage){
                        drawable = R.drawable.ic_file_label_white;
                    }else{
                        drawable = R.drawable.ic_file_label;
                    }
                }
                ((ImageView)fileRL.getChildAt(Const.ChildrenInFileLayout.ICON)).setImageResource(drawable);
            }

        }else if(message.type == Const.MessageType.TYPE_LOCATION){

            fileRL.setVisibility(View.VISIBLE);
            showAllChildrenFromLayout(fileRL);

            if(isMyMessage){
                info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
            }else{
                info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
            }

            int drawable = 0;
            if(isMyMessage){
                drawable = R.drawable.ic_location_label_white;
            }else{
                drawable = R.drawable.ic_location_label;
            }
            ((ImageView)fileRL.getChildAt(Const.ChildrenInFileLayout.ICON)).setImageResource(drawable);
            ((TextView)fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_NAME)).setText(message.message);
            ((TextView)fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_DOWNLOAD)).setText(fileRL.getContext().getResources().getString(R.string.show_location_on_map));
            fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_SIZE).setVisibility(View.GONE);

        }else if(message.type == Const.MessageType.TYPE_CONTACT){

            fileRL.setVisibility(View.VISIBLE);
            showAllChildrenFromLayout(fileRL);

            if(isMyMessage){
                info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
            }else{
                info = (ImageView) fileRL.getChildAt(Const.ChildrenInFileLayout.INFO);
            }

            int drawable = 0;
            if(isMyMessage){
                drawable = R.drawable.ic_contact_label_white;
            }else{
                drawable = R.drawable.ic_contact_label;
            }
            ((ImageView)fileRL.getChildAt(Const.ChildrenInFileLayout.ICON)).setImageResource(drawable);
            String[] contactData = VCardParser.getNameAndFirstPhoneAndFirstEmail(message.message);
            ((TextView) fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_NAME)).setText(contactData[Const.ContactData.NAME]);
            if(contactData[Const.ContactData.EMAIL] != null){
                ((TextView) fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_DOWNLOAD)).setText(contactData[Const.ContactData.EMAIL]);
            }else{
               fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_DOWNLOAD).setVisibility(View.GONE);
            }
            if(contactData[Const.ContactData.PHONE] != null){
                ((TextView) fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_SIZE)).setText(contactData[Const.ContactData.PHONE]);
            }else{
                fileRL.getChildAt(Const.ChildrenInFileLayout.FILE_SIZE).setVisibility(View.GONE);
            }

        }

        if(isMyMessage){
            if(message.status == Const.MessageStatus.SENT){
                holder.myMessageStatus.setBackgroundResource(R.drawable.icon_sent);
            } else if (message.status == Const.MessageStatus.DELIVERED) {
                holder.myMessageStatus.setBackgroundResource(R.drawable.icon_delivered);
            } else {
                holder.myMessageStatus.setBackgroundResource(R.drawable.icon_delivered);
            }
        }

        if(isMyMessage){
            if(position != 0 && isMessageFromUser(data.get(position - 1), myUser)){
                holder.myAvatar.setVisibility(View.GONE);
                holder.myNameAndTime.setVisibility(View.GONE);
            }else{
                holder.myAvatar.setVisibility(View.VISIBLE);
                holder.myNameAndTime.setVisibility(View.VISIBLE);
                ImageLoaderSpice.getInstance(holder.myAvatar.getContext()).displayImage(holder.myAvatar, myUser.avatarURL, 0);

                String name = myUser.name;
                String time = message.getTimeCreated(holder.myNameAndTime.getResources());
                Spannable span = new SpannableString(name + " " +time);
                span.setSpan(new StyleSpan(Typeface.BOLD), 0, name.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                span.setSpan(new ForegroundColorSpan(holder.myNameAndTime.getResources().getColor(R.color.gray_light_color)), name.length() + 1, span.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                holder.myNameAndTime.setText(span);
            }
        }else {
            if(position != 0 && !isMessageFromUser(data.get(position - 1), myUser)){
                holder.youAvatar.setVisibility(View.INVISIBLE);
                holder.youNameAndTime.setVisibility(View.GONE);
            }else{
                holder.youAvatar.setVisibility(View.VISIBLE);
                holder.youNameAndTime.setVisibility(View.VISIBLE);
                ImageLoaderSpice.getInstance(holder.youAvatar.getContext()).displayImage(holder.youAvatar, message.user.avatarURL, 0);

                String name = message.user.name;
                String time = message.getTimeCreated(holder.myNameAndTime.getResources());
                Spannable span = new SpannableString(name + " " +time);
                span.setSpan(new StyleSpan(Typeface.BOLD), 0, name.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                span.setSpan(new ForegroundColorSpan(holder.myNameAndTime.getResources().getColor(R.color.gray_light_color)), name.length() + 1, span.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                holder.youNameAndTime.setText(span);
            }
        }

        holder.parentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(lastItemListener != null){
                    lastItemListener.onClickItem(message);
                }
            }
        });

        // info is null when type is text, user leave or user join
        if(info != null){
            info.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (lastItemListener != null) {
                        lastItemListener.onInfoClick(message);
                    }
                }
            });
        }

        if(position == 0){
            if(lastItemListener != null){
                lastItemListener.onLastItem();
            }
        }

    }

    /**
     * check is message from user
     * @param message - message with user
     * @param user - user for check
     * @return boolean is message from user
     */
    private boolean isMessageFromUser(Message message, User user){
        String userId = null;
        boolean isMyMessage = false;
        if(message.user != null && message.user.userID != null){
            userId = message.user.userID;
        }else{
            userId = message.userID;
        }

        if(userId.equals(user.userID)){
            isMyMessage = true;
        }

        return isMyMessage;
    }

    /**
     * set visibility of all view from given ViewGroup to visible
     * @param layout
     */
    private void showAllChildrenFromLayout(ViewGroup layout){
        for(int i = 0; i < layout.getChildCount(); i++){
            layout.getChildAt(i).setVisibility(View.VISIBLE);
        }
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    /**
     * listener for last item showed and for click on item
     */
    public interface OnLastItemAndOnClickListener{
        /**
         * triggered when last item show in adapter
         */
        public void onLastItem();

        /**
         * triggered when user click on item
         *
         * @param item data from clicked item
         */
        public void onClickItem(Message item);

        /**
         * triggered when user click on info button
         *
         * @param item data from clicked item
         */
        public void onInfoClick(Message item);
    }

}

redpajama_set_name: RedPajamaGithub


text:
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 4)
timeout 15
preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(Sequel::Model) and
    Sequel::Model.db.disconnect
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(Sequel::Model) and
    Sequel::Model.db.connect(ENV["DATABASE_URL"])
end


text:
#include "storeman.h"

#include <QtCore/private/qobject_p.h>
#include <QCache>
#include <QSettings>
#include <QTimer>

class StoremanPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(Storeman)

    void refreshRepos();

    QSettings settings;
    QTimer    updatesTimer;
    QCache<quint32, OrnApplication> appsCache;
};


text:
package io.fabric8.jaxb.dynamic;

import javax.xml.bind.JAXBContext;

import org.apache.camel.converter.jaxb.JaxbDataFormat;
import org.apache.camel.util.ObjectHelper;

/**
 * An implementation of {@link JaxbDataFormat} which can deal with compiling XSD files on the fly
 * to create the JAXB context
 */
public class DynamicJaxbDataFormat extends JaxbDataFormat implements CompileResultsHandler {
    private DynamicCompiler compiler;
    private CompileResults compileResults;

    public DynamicJaxbDataFormat() {
    }

    public DynamicJaxbDataFormat(JAXBContext context) {
        super(context);
    }

    public DynamicJaxbDataFormat(String contextPath) {
        super(contextPath);
    }

    public DynamicCompiler getCompiler() {
        return compiler;
    }

    public void setCompiler(DynamicCompiler compiler) throws Exception {
        this.compiler = compiler;
        if (compiler != null) {
            compiler.setHandler(this);
        }
    }

    public void init() throws Exception {
        ObjectHelper.notNull(getCompiler(), "compiler");
    }

    /**
     * Whenever any kind of compiler is performed this is the handler method to pass in the results
     */
    @Override
    public void onCompileResults(CompileResults compileResults) {
        this.compileResults = compileResults;
        setContext(compileResults.getJAXBContext());
    }

    /**
     * Returns the class loader created by the dynamic compilation or null if none has been created yet
     */
    public ClassLoader getClassLoader() {
        if (compileResults != null) {
            return compileResults.getClassLoader();
        }
        return null;
    }

    public CompileResults getCompileResults() {
        return compileResults;
    }
}


text:
require 'rubygems'
require 'amee-data-abstraction'
require 'amee-data-persistence'
require 'amee/analytics/result'
require 'amee/analytics/calculation_collection_analytics_support'
require 'amee/analytics/terms_list_analytics_support'
require 'amee/analytics/term_analytics_support'

::AMEE::DataAbstraction::CalculationCollection.send :include, AMEE::Analytics::CalculationCollectionAnalyticsSupport
::AMEE::DataAbstraction::TermsList.send :include, AMEE::Analytics::TermsListAnalyticsSupport
::AMEE::DataAbstraction::Term.send :include, AMEE::Analytics::TermAnalyticsSupport


text:
use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/lib";

use tools;

our $VERSION = "0.005";

my $name_rexp    = qr{[A-Za-z_]+[A-Za-z0-9_]*};
my $keyword_rexp = qr{if|else|end|omp};

sub error($$$) {
    my ( $input, $msg, $bulk ) = @_;
    my $pos = pos( $$bulk );
    $$bulk =~ m{^(.*?)\G(.*?)$}m or die "Internal error";
    my ( $pre, $post ) = ( $1, $2 );
    my $n = scalar( @{ [ substr( $$bulk, 0, $pos ) =~ m{\n}g ] } ) + 1;
    runtime_error( "\"$input\" line $n: $msg:", ">>> " . $pre . "--[HERE]-->" . $post );
}; # sub error

sub evaluate($$$\$) {
    my ( $expr, $strict, $input, $bulk ) = @_;
    my $value;
    { # Signal handler will be restored on exit from this block.
        # In case of "use strict; use warnings" eval issues warnings to stderr. This direct
        # output may confuse user, so we need to catch it and prepend with our info.
        local $SIG{ __WARN__ } = sub { die @_; };
        $value =
            eval(
                "package __EXPAND_VARS__;\n" .
                ( $strict ? "use strict; use warnings;\n" : "no strict; no warnings;\n" ) .
                $expr
            );
    };
    if ( $@ ) {
        # Drop location information -- increasing eval number and constant "line 3"
        # is useless for the user.
        $@ =~ s{ at \(eval \d+\) line \d+}{}g;
        $@ =~ s{\s*\z}{};
        error( $input, "Cannot evaluate expression \"\${{$expr}}\": $@", $bulk );
    }; # if
    if ( $strict and not defined( $value ) ) {
        error( $input, "Substitution value is undefined", $bulk );
    }; # if
    return $value;
}; # sub evaluate

#
# Parse command line.
#

my ( @defines, $input, $output, $strict );
get_options(
    "D|define=s" => \@defines,
    "strict!"    => \$strict,
);
if ( @ARGV < 2 ) {
    cmdline_error( "Not enough argument" );
}; # if
if ( @ARGV > 2 ) {
    cmdline_error( "Too many argument(s)" );
}; # if
( $input, $output ) = @ARGV;

foreach my $define ( @defines ) {
    my ( $equal, $name, $value );
    $equal = index( $define, "=" );
    if ( $equal < 0 ) {
        $name = $define;
        $value = "";
    } else {
        $name = substr( $define, 0, $equal );
        $value = substr( $define, $equal + 1 );
    }; # if
    if ( $name eq "" ) {
        cmdline_error( "Illegal definition: \"$define\": variable name should not be empty." );
    }; # if
    if ( $name !~ m{\A$name_rexp\z} ) {
        cmdline_error(
            "Illegal definition: \"$define\": " .
                "variable name should consist of alphanumeric characters."
        );
    }; # if
    eval( "\$__EXPAND_VARS__::$name = \$value;" );
    if ( $@ ) {
        die( "Internal error: $@" );
    }; # if
}; # foreach $define

#
# Do the work.
#

my $bulk;

# Read input file.
$bulk = read_file( $input );

# Do the replacements.
$bulk =~
    s{(?:\$($keyword_rexp)|\$($name_rexp)|\${{(.*?)}})}
    {
        my $value;
        if ( defined( $1 ) ) {
            # Keyword. Leave it as is.
            $value = "\$$1";
        } elsif ( defined( $2 ) ) {
            # Variable to expand.
            my $name = $2;
            $value = eval( "\$__EXPAND_VARS__::$name" );
            if ( $@ ) {
                die( "Internal error" );
            }; # if
            if ( $strict and not defined( $value ) ) {
                error( $input, "Variable \"\$$name\" not defined", \$bulk );
            }; # if
        } else {
            # Perl code to evaluate.
            my $expr = $3;
            $value = evaluate( $expr, $strict, $input, $bulk );
        }; # if
        $value;
    }ges;

# Process conditionals.
# Dirty patch! Nested conditionals not supported!
# TODO: Implement nested constructs.
$bulk =~
    s{^\$if +([^\n]*) *\n(.*\n)\$else *\n(.*\n)\$end *\n}
    {
        my ( $expr, $then_part, $else_part ) = ( $1, $2, $3 );
        my $value = evaluate( $expr, $strict, $input, $bulk );
        if ( $value ) {
            $value = $then_part;
        } else {
            $value = $else_part;
        }; # if
    }gesm;

# Write output.
write_file( $output, \$bulk );

exit( 0 );

__END__

=pod

=head1 NAME

B<expand-vars.pl> -- Simple text preprocessor.

=head1 SYNOPSIS

B<expand-vars.pl> I<OPTION>... I<input> I<output>

=head1 OPTIONS

=over

=item B<-D> I<name>[B<=>I<value>]

=item B<--define=>I<name>[B<=>I<value>]

Define variable.

=item B<--strict>

In strict mode, the script issues error on using undefined variables and executes Perl code
with C<use strict; use warnings;> pragmas.

=back

=head2 Standard Options

=over

=item B<--doc>

=item B<--manual>

Print full help message and exit.

=item B<--help>

Print short help message and exit.

=item B<--usage>

Print very short usage message and exit.

=item B<--verbose>

Do print informational messages.

=item B<--version>

Print version and exit.

=item B<--quiet>

Work quiet, do not print informational messages.

=back

=head1 ARGUMENTS

=over

=item I<input>

Input file name.

=item I<output>

Output file name.

=back

=head1 DESCRIPTION

This script reads input file, makes substitutes and writes output file.

There are two form of substitutes:

=over

=item Variables

Variables are referenced in input file in form:

    $name

Name of variable should consist of alphanumeric characters (Latin letters, digits, and underscores).
Variables are defined in command line with C<-D> or C<--define> options.

=item Perl Code

Perl code is specified in input file in form:

    ${{ ...code... }}

The code is evaluated, and is replaced with its result. Note: in strict mode, you should declare
variable before use. See examples.

=back

=head1 EXAMPLES

Replace occurrences of C<$year>, C<$month>, and C<$day> in C<input.txt> file with C<2007>, C<09>, C<01>
respectively and write result to C<output.txt> file:

    $ cat input.var
    Today is $year-$month-$day.
    $ expand-vars.pl -D year=2007 -D month=09 -D day=01 input.var output.txt && cat output.txt
    Today is 2007-09-01.

Using Perl code:

    $ cat input.var
    ${{ localtime(); }}
    $ expand-vars.pl -D year=2007 -D month=09 -D day=01 input.var output.txt && cat output.txt
    Now Tue May  5 20:54:13 2009

Using strict mode for catching bugs:

    $ cat input.var
    ${{ "year : " . substr( $date, 0, 4 ); }}
    $ expand-vars.pl input.var output.txt && cat output.txt
    year :

Oops, why it does not print year? Let us use strict mode:

    $ expand-vars.pl --strict input.var output.txt && cat output.txt
    expand-vars.pl: (x) "test.var": Cannot evaluate expression "${{ "year : " . substr( $date, 0, 4 ); }}": Global symbol "$date" requires explicit package name

Ok, variable is not defined. Let us define it:

    $ expand-vars.pl --strict -D date=20090501 input.var output.txt && cat output.txt
    expand-vars.pl: (x) "test.var": Cannot evaluate expression "${{ "year : " . substr( $date, 0, 4 ); }}": Variable "$date" is not imported

What is wrong? Variable should be declared:

    $ cat input.var
    ${{ our $date; "year : " . substr( $date, 0, 4 ); }}
    $ expand-vars.pl --strict -D date=20090501 input.var output.txt && cat output.txt
    year : 2009

=cut

# end of file #


text:
BSLS_IDENT_RCSID(bdlbb_blobutil_cpp, "$Id$ $CSID$")

#include <bdlb_print.h>
#include <bslma_allocator.h>
#include <bslma_deallocatorproctor.h>
#include <bslma_default.h>
#include <bsls_assert.h>
#include <bsls_types.h>

#include <bsl_algorithm.h>

#include <bsl_c_ctype.h>
#include <bsl_iostream.h>

namespace BloombergLP {
namespace {

// HELPER FUNCTION
void copyFromPlace(char                *dstBuffer,
                   const bdlbb::Blob&   srcBlob,
                   bsl::pair<int, int>  place,
                   int                  length)
    // Copy the specified 'length' bytes, starting at the specified 'place' in
    // the specified 'srcBlob', to the specified 'dstBuffer'.  The behavior of
    // this function is undefined unless '0 < length', 'place' represents an
    // actual character position in 'srcBlob', 'srcBlob' has at least 'length'
    // bytes starting at 'place', and 'dstBuffer' has room for 'length' bytes.
{
    BSLS_ASSERT(place.first < srcBlob.numBuffers());
    BSLS_ASSERT(place.second < srcBlob.buffer(place.first).size());
    BSLS_ASSERT(0 < length);
    BSLS_ASSERT(0 != dstBuffer);
    BSLS_ASSERT(length <= srcBlob.totalSize());
    // Verifying place + length is in bounds would be messy. Callers do it.

    int copied = 0;
    do {
        const bdlbb::BlobBuffer& buf = srcBlob.buffer(place.first);
        int toCopy = bsl::min(length - copied, buf.size() - place.second);
        bsl::memcpy(dstBuffer + copied, buf.data() + place.second, toCopy);
        copied += toCopy;
        ++place.first;
        place.second = 0;
    } while (copied < length);
}

}  // close unnamed namespace

namespace bdlbb {

                              // ---------------
                              // struct BlobUtil
                              // ---------------

// CLASS METHODS
void BlobUtil::append(Blob *dest, const Blob& source, int offset, int length)
{
    BSLS_ASSERT(0 != dest);
    BSLS_ASSERT(0 <= offset);
    BSLS_ASSERT(0 <= length);
    BSLS_ASSERT(offset <= source.length());
    BSLS_ASSERT(length <= source.length() - offset);

    if (0 == length) {
        return;                                                       // RETURN
    }

    bsl::pair<int, int> beginPlace = findBufferIndexAndOffset(source, offset);
    int                 sourceBufferIndex  = beginPlace.first;
    int                 offsetInThisBuffer = beginPlace.second;

    const int destStartLength = dest->length();

    dest->trimLastDataBuffer();
    dest->removeUnusedBuffers();

    // Calculate how much room will be need in the buffer vector in 'dest' to
    // accomodate the new buffers that will be appended.

    {
        const int endPlaceOffset = bsl::min(source.length() - 1,
                                            offset + length);
        bsl::pair<int, int> endPlace =
                     bdlbb::BlobUtil::findBufferIndexAndOffset(source,
                                                               endPlaceOffset);
        dest->reserveBufferCapacity(dest->numDataBuffers() +
                                     (endPlace.first - sourceBufferIndex) + 1);
    }

    // Add aliased source buffer.

    int numBytesRemaining = length;

    {
        BlobBuffer src = source.buffer(sourceBufferIndex);

        if (0 < offsetInThisBuffer) {
            src.buffer().loadAlias(src.buffer(),
                                   src.data() + offsetInThisBuffer);
            src.setSize(src.size() - offsetInThisBuffer);
        }

        if (src.size() > numBytesRemaining) {
            src.setSize(numBytesRemaining);
        }

        dest->appendDataBuffer(src);

        ++sourceBufferIndex;
        numBytesRemaining -= src.size();
    }

    // Add remaining buffers.

    while (0 < numBytesRemaining) {
        BSLS_ASSERT(sourceBufferIndex < source.numBuffers());

        BlobBuffer src = source.buffer(sourceBufferIndex);

        if (src.size() > numBytesRemaining) {
            src.setSize(numBytesRemaining);
        }

        dest->appendDataBuffer(src);

        ++sourceBufferIndex;
        numBytesRemaining -= src.size();
    }

    // Set new length.

    int newLength = destStartLength + length;

    BSLS_ASSERT(-numBytesRemaining == dest->totalSize() - newLength);
    BSLS_ASSERT(newLength <= dest->totalSize());

    (void)newLength;  // quash potential compiler warning
}

void BlobUtil::append(Blob *dest, const char *source, int offset, int length)
{
    BSLS_ASSERT(0 != dest);
    BSLS_ASSERT(0 != source || 0 == length);
    BSLS_ASSERT(0 <= offset);
    BSLS_ASSERT(0 <= length);

    int destBufferIndex = bsl::max(0, dest->numDataBuffers() - 1);
    int writePosition   = dest->lastDataBufferLength();

    dest->setLength(dest->length() + length);

    int numBytesLeft   = length;
    int numBytesCopied = 0;

    while (0 < numBytesLeft) {
        const BlobBuffer& buffer = dest->buffer(destBufferIndex);

        int numBytesAvailable = buffer.size() - writePosition;
        int numBytesToCopy    = bsl::min(numBytesAvailable, numBytesLeft);

        if (0 == numBytesToCopy) {
            writePosition = 0;
            ++destBufferIndex;
            continue;
        }

        BSLS_ASSERT(0 <= numBytesToCopy);

        bsl::memcpy(buffer.data() + writePosition,
                    source + offset + numBytesCopied,
                    numBytesToCopy);

        numBytesCopied += numBytesToCopy;
        numBytesLeft -= numBytesToCopy;

        if (0 < numBytesLeft) {
            ++destBufferIndex;
            writePosition = 0;
        }
    }
}

void BlobUtil::erase(Blob *blob, int offset, int length)
{
    BSLS_ASSERT(0 != blob);
    BSLS_ASSERT(offset >= 0);
    BSLS_ASSERT(length >= 0);
    BSLS_ASSERT(offset <= blob->length());
    BSLS_ASSERT(length <= blob->length() - offset);

    if (0 == length) {
        return;                                                       // RETURN
    }

    bsl::pair<int, int> place = findBufferIndexAndOffset(*blob, offset);
    int                 currBufferIdx    = place.first;
    int                 leadingBufferLen = place.second;

    if (currBufferIdx >= blob->numDataBuffers()) {
        return;                                                       // RETURN
    }

    if (leadingBufferLen) {
        const BlobBuffer&     leadingBuffer = blob->buffer(currBufferIdx);
        bsl::shared_ptr<char> leadingShptr(leadingBuffer.buffer(),
                                           leadingBuffer.data());
        BlobBuffer            leadingPartialBuffer;

        leadingPartialBuffer.setSize(leadingBufferLen);

        blob->insertBuffer(currBufferIdx, leadingPartialBuffer);
        leadingPartialBuffer.buffer().swap(leadingShptr);
        blob->swapBufferRaw(currBufferIdx, &leadingPartialBuffer);

        // Adjust the length of the data to be deleted to include the length of
        // the leading buffer that we just prepended and increment
        // currBufferIdx to show that the next buffer to be deleted should be
        // after the prepended buffer.

        ++currBufferIdx;
        length += leadingBufferLen;
    }

    int nextBufferIdx = currBufferIdx;

    while (length > 0) {
        const int nextBufferSize = blob->buffer(nextBufferIdx).size();

        if (nextBufferSize <= length) {
            ++nextBufferIdx;
            length -= nextBufferSize;
        }
        else {
            break;
        }
    }

    blob->removeBuffers(currBufferIdx, nextBufferIdx - currBufferIdx);

    if (length > 0) {
        const BlobBuffer& currBlobBuffer = blob->buffer(currBufferIdx);
        const int         currBufferSize = currBlobBuffer.size();

        int       numBytesToAdjust = 0;
        const int lastDataBufLen   = blob->lastDataBufferLength();
        if (currBufferIdx == blob->numDataBuffers() - 1 &&
            lastDataBufLen < currBufferSize) {
            numBytesToAdjust = currBufferSize - lastDataBufLen;
        }

        bsl::shared_ptr<char> trailingShptr(currBlobBuffer.buffer(),
                                            currBlobBuffer.data() + length);

        BlobBuffer trailingPartialBuffer;
        trailingPartialBuffer.setSize(currBufferSize - length);

        blob->insertBuffer(currBufferIdx, trailingPartialBuffer);
        trailingPartialBuffer.buffer().swap(trailingShptr);
        blob->swapBufferRaw(currBufferIdx, &trailingPartialBuffer);
        blob->removeBuffer(currBufferIdx + 1);
        if (numBytesToAdjust) {
            blob->setLength(blob->length() - numBytesToAdjust);
        }
    }
}

void BlobUtil::insert(Blob        *dest,
                      int          destOffset,
                      const Blob&  source,
                      int          sourceOffset,
                      int          sourceLength)
{
    BSLS_ASSERT(0 != dest);

    // TBD: optimize this also

    Blob result;

    append(&result, *dest, 0, destOffset);
    append(&result, source, sourceOffset, sourceLength);
    append(&result, *dest, destOffset);

    *dest = result;
}

bsl::pair<int, int> BlobUtil::findBufferIndexAndOffset(const Blob& blob,
                                                       int         position)
{
    BSLS_ASSERT(0 <= position);
    BSLS_ASSERT(position < blob.totalSize());

    bsl::pair<int, int>  result(0, position);
    const BlobBuffer    *buffer = &(blob.buffer(0));
    for (; buffer->size() <= result.second; ++buffer) {
        result.first++;
        result.second -= buffer->size();
        BSLS_ASSERT(result.first < blob.numBuffers());
    }
    return result;
}

void BlobUtil::copy(char        *dstBuffer,
                    const Blob&  srcBlob,
                    int          position,
                    int          length)
{
    BSLS_ASSERT(0 <= position);
    BSLS_ASSERT(0 <= length);
    BSLS_ASSERT(position <= srcBlob.totalSize() - length);
    BSLS_ASSERT(dstBuffer != 0);

    if (0 < length) {
        copyFromPlace(dstBuffer,
                      srcBlob,
                      findBufferIndexAndOffset(srcBlob, position),
                      length);
    }
}

void BlobUtil::copy(Blob *dst, int dstOffset, const char *src, int length)
{
    BSLS_ASSERT(0 <= dstOffset);
    BSLS_ASSERT(0 <= length);

    if (0 != length) {
        BSLS_ASSERT(dst);
        BSLS_ASSERT(src);
        BSLS_ASSERT(dstOffset <= dst->length() - length);

        bsl::pair<int, int> place = findBufferIndexAndOffset(*dst, dstOffset);

        int copied    = 0;
        int bufIdx    = place.first;
        int bufOffset = place.second;

        do {
            const BlobBuffer& buf = dst->buffer(bufIdx);
            int toCopy = bsl::min(length - copied, buf.size() - bufOffset);
            bsl::memcpy(buf.data() + bufOffset, src + copied, toCopy);
            copied += toCopy;
            ++bufIdx;
            bufOffset = 0;
        } while (copied < length);
    }
}

void BlobUtil::copy(Blob        *dst,
                    int          dstOffset,
                    const Blob&  src,
                    int          srcOffset,
                    int          length)
{
    BSLS_ASSERT(0 <= dstOffset);
    BSLS_ASSERT(0 <= srcOffset);
    BSLS_ASSERT(0 <= length);
    BSLS_ASSERT(srcOffset <= src.length() - length);

    if (0 != length) {
        BSLS_ASSERT(dst);
        BSLS_ASSERT(dstOffset <= dst->length() - length);

        bsl::pair<int, int> dstPlace =
            findBufferIndexAndOffset(*dst, dstOffset);
        bsl::pair<int, int> srcPlace =
            findBufferIndexAndOffset(src, srcOffset);

        int copied       = 0;
        int dstBufIdx    = dstPlace.first;
        int dstBufOffset = dstPlace.second;
        int srcBufIdx    = srcPlace.first;
        int srcBufOffset = srcPlace.second;

        do {
            const BlobBuffer& dstBuf = dst->buffer(dstBufIdx);
            const BlobBuffer& srcBuf = src.buffer(srcBufIdx);

            int toCopy = bsl::min(
                bsl::min(length - copied, dstBuf.size() - dstBufOffset),
                srcBuf.size() - srcBufOffset);

            bsl::memcpy(dstBuf.data() + dstBufOffset,
                        srcBuf.data() + srcBufOffset,
                        toCopy);

            copied += toCopy;

            if (toCopy == dstBuf.size() - dstBufOffset) {
                ++dstBufIdx;
                dstBufOffset = 0;
            }
            else {
                dstBufOffset += toCopy;
            }

            if (toCopy == srcBuf.size() - srcBufOffset) {
                ++srcBufIdx;
                srcBufOffset = 0;
            }
            else {
                srcBufOffset += toCopy;
            }
        } while (copied < length);
    }
}

char *BlobUtil::getContiguousRangeOrCopy(char        *dstBuffer,
                                         const Blob&  srcBlob,
                                         int          position,
                                         int          length,
                                         int          alignment)
{
    BSLS_ASSERT(dstBuffer != 0);
    BSLS_ASSERT(0 <= position);
    BSLS_ASSERT(0 < length);
    BSLS_ASSERT(length <= srcBlob.totalSize());
    BSLS_ASSERT(position <= srcBlob.totalSize() - length);
    BSLS_ASSERT(0 < alignment);
    BSLS_ASSERT(0 == (alignment & (alignment - 1)));
    BSLS_ASSERT(0 == (reinterpret_cast<bsls::Types::IntPtr>(dstBuffer) &
                      (alignment - 1)));

    bsl::pair<int, int>  place  = findBufferIndexAndOffset(srcBlob, position);
    const BlobBuffer&    buffer = srcBlob.buffer(place.first);
    char                *p      = buffer.data() + place.second;
    if (0 != (reinterpret_cast<bsls::Types::IntPtr>(p) & (alignment - 1)) ||
        buffer.size() - place.second < length) {
        copyFromPlace(dstBuffer, srcBlob, place, length);
        p = dstBuffer;
    }
    return p;
}

char *BlobUtil::getContiguousDataBuffer(Blob              *blob,
                                        int                addLength,
                                        BlobBufferFactory *factory)
{
    BSLS_ASSERT(factory != 0);
    BSLS_ASSERT(blob != 0);
    BSLS_ASSERT(0 < addLength);

    int index  = blob->numDataBuffers() - 1;
    int offset = blob->lastDataBufferLength();
    if (index < 0 || blob->buffer(index).size() - offset < addLength) {
        blob->trimLastDataBuffer();
        int size = offset = 0;
        while (++index < blob->numBuffers() &&
               0 == (size = blob->buffer(index).size())) {
            ;  // skip past any zero-size buffers
        }
        if (size < addLength) {
            index = blob->numDataBuffers();  // found nothing usable
            BlobBuffer buffer;
            factory->allocate(&buffer);
            BSLS_ASSERT(addLength <= buffer.size());
            blob->insertBuffer(index, buffer);
        }
    }
    blob->setLength(blob->length() + addLength);
    return blob->buffer(index).data() + offset;
}

bsl::ostream& BlobUtil::asciiDump(bsl::ostream& stream, const Blob& source)
{
    int numBytes = source.length();

    for (int numBytesRemaining = numBytes, i = 0; 0 < numBytesRemaining; ++i) {
        BSLS_ASSERT(i < source.numBuffers());

        const BlobBuffer& buffer = source.buffer(i);

        int bytesToWrite = numBytesRemaining < buffer.size()
                               ? numBytesRemaining
                               : buffer.size();

        stream.write(buffer.data(), bytesToWrite);
        numBytesRemaining -= bytesToWrite;
    }

    return stream;
}

bsl::ostream& BlobUtil::hexDump(bsl::ostream& stream,
                                const Blob&   source,
                                int           offset,
                                int           length)
{
    BSLS_ASSERT(0 <= offset);
    BSLS_ASSERT(0 <= length);
    BSLS_ASSERT(length <= source.totalSize());
    BSLS_ASSERT(offset <= source.totalSize() - length);

    if (0 == source.numDataBuffers()) {
        return stream;                                                // RETURN
    }

    enum { k_NUM_STATIC_BUFFERS = 32 };

    typedef bsl::pair<const char *, int> BufferInfo;

    BufferInfo  staticBuffers[k_NUM_STATIC_BUFFERS];
    BufferInfo *buffers       = staticBuffers;
    int         numBufferInfo = 0;

    bslma::DeallocatorProctor<bslma::Allocator> deallocationGuard(
        0, bslma::Default::defaultAllocator());

    if (source.numDataBuffers() > k_NUM_STATIC_BUFFERS) {
        // This works because we do not need to call the constructor on a pair
        // of two built-in types.

        buffers = static_cast<BufferInfo *>(
                      bslma::Default::defaultAllocator()->allocate(
                                source.numDataBuffers() * sizeof(BufferInfo)));
        deallocationGuard.reset(buffers);
    }

    bsl::pair<int, int> place       = findBufferIndexAndOffset(source, offset);
    int                 bufferIndex = place.first;
    int                 offsetInThisBuffer = place.second;

    if (bufferIndex >= source.numDataBuffers()) {
        return stream;                                                // RETURN
    }

    BSLS_ASSERT(bufferIndex < source.numDataBuffers());

    int numBytesLeft   = length;
    int numBytesCopied = 0;

    while (0 < numBytesLeft) {
        BSLS_ASSERT(bufferIndex < source.numDataBuffers());

        const BlobBuffer& buffer = source.buffer(bufferIndex);

        int startingIndex = 0 == numBytesCopied ? offsetInThisBuffer : 0;

        int numBytesAvailable = bufferIndex == source.numDataBuffers() - 1
                                    ? source.lastDataBufferLength()
                                    : buffer.size() - startingIndex;

        int numBytesToDump = bsl::min(numBytesAvailable, numBytesLeft);

        if (0 == numBytesToDump) {
            ++bufferIndex;
            continue;
        }

        BSLS_ASSERT(0 <= numBytesToDump);

        buffers[numBufferInfo] =
            bsl::make_pair(buffer.data() + startingIndex, numBytesToDump);
        ++numBufferInfo;

        numBytesCopied += numBytesToDump;
        numBytesLeft -= numBytesToDump;

        if (0 < numBytesLeft) {
            ++bufferIndex;
        }
    }

    return bdlb::Print::hexDump(stream, buffers, numBufferInfo);
}

int BlobUtil::compare(const Blob& a, const Blob& b)
{
    // Upon entry, establish 'lhs' and 'rhs' as aliases for 'a' and 'b',
    // respectively.  The logic of this function is such that the blob with the
    // smaller current blob buffer is on the left-hand side of comparison
    // operations.  Consequently, using 'lhs' and 'rhs' in place of 'a' and 'b'
    // enhances the clarity of the algorithm.

    const Blob& lhs = a;
    const Blob& rhs = b;

    const int lhsLen = lhs.length();
    const int rhsLen = rhs.length();
    const int minLen = bsl::min(lhsLen, rhsLen);

    if (0 == minLen) {
        return lhsLen - rhsLen;                                       // RETURN
    }

    const BlobBuffer& lhsBlobBuffer = lhs.buffer(0);
    const BlobBuffer& rhsBlobBuffer = rhs.buffer(0);

    // Keep track of the size of the blob buffers and store the smaller blob
    // buffer in the 'lhs' blob buffer.

    bool isLhsBufSmaller = lhsBlobBuffer.size() < rhsBlobBuffer.size();

    int lhsBufSize;
    int rhsBufSize;

    const char *lhsPtr;
    const char *rhsPtr;

    const Blob *lhsBlob;
    const Blob *rhsBlob;

    if (isLhsBufSmaller) {
        lhsBufSize = lhsBlobBuffer.size();
        lhsPtr     = lhsBlobBuffer.data();
        lhsBlob    = &lhs;

        rhsBufSize = rhsBlobBuffer.size();
        rhsPtr     = rhsBlobBuffer.data();
        rhsBlob    = &rhs;
    }
    else {
        lhsBufSize = rhsBlobBuffer.size();
        lhsPtr     = rhsBlobBuffer.data();
        lhsBlob    = &rhs;

        rhsBufSize = lhsBlobBuffer.size();
        rhsPtr     = lhsBlobBuffer.data();
        rhsBlob    = &lhs;
    }

    // Keep track of which buffer we are comparing.

    int lhsBufIdx = 0;
    int rhsBufIdx = 0;

    int numBytesRemaining = minLen;

    while (numBytesRemaining > 0) {
        const int numBytesToCompare = bsl::min(lhsBufSize, numBytesRemaining);

        // Note this code can tolerate the case where '0 == lhsBufSize'.  We
        // just DROP through and increment to the next buffer.  Note that when
        // the two buffers are the same size, an iteration is made where
        // '0 == lhsBufSize' holds because we only advance one of the two
        // buffers in each iteration of the loop.

        const int rc = bsl::memcmp(static_cast<const void *>(lhsPtr),
                                   static_cast<const void *>(rhsPtr),
                                   numBytesToCompare);

        if (rc) {
            return isLhsBufSmaller ? rc : -rc;                        // RETURN
        }

        numBytesRemaining -= numBytesToCompare;

        if (0 == numBytesRemaining) {
            break;
        }

        rhsBufSize -= numBytesToCompare;

        ++lhsBufIdx;  // advance to next 'lhs' blob buffer
        BSLS_ASSERT(lhsBufIdx < lhsBlob->numDataBuffers());

        const BlobBuffer& nextLhsBlobBuffer = lhsBlob->buffer(lhsBufIdx);
        const int         nextLhsBufSize    = nextLhsBlobBuffer.size();
        if (rhsBufSize >= nextLhsBufSize) {
            // The next 'lhs' blob buffer is still the smaller buffer.

            lhsBufSize = nextLhsBufSize;
            lhsPtr     = nextLhsBlobBuffer.data();

            rhsPtr = rhsPtr + numBytesToCompare;
        }
        else {
            // The new 'lhs' blob buffer is larger than the 'rhs' blob buffer,
            // so swap them so that the smaller buffer is on the left.

            isLhsBufSmaller = !isLhsBufSmaller;

            lhsBufSize = rhsBufSize;
            lhsPtr     = rhsPtr + numBytesToCompare;

            rhsBufSize = nextLhsBufSize;
            rhsPtr     = nextLhsBlobBuffer.data();

            using bsl::swap;
            swap(lhsBlob, rhsBlob);
            swap(lhsBufIdx, rhsBufIdx);
        }
    }

    // Everything is the same, only the lengths may differ.

    return lhsLen - rhsLen;
}
}  // close package namespace

}  // close enterprise namespace

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------


text:
class Category < ActiveRecord::Base
  has_many :books
  default_serialize_options :json => {:dasherize => false}
end


text:
import java.util.ArrayList;

/**
 * Classe para o mapa do jogo
 */
public class Mapa
{
	private ArrayList<Posicao> mapa;
	private int largura = 5;
	private int comprimento = 5;

	/**
	 * Construtor para o objeto
	 *
	 * @param      largura      A largura do mapa
	 * @param      comprimento  O comprimento do mapa
	 */
	public Mapa (int largura_, int comprimento_)
	{
		largura = largura_;
		comprimento = comprimento_;
		mapa = new ArrayList<Posicao>();
		this.inicializaMapa();
	}

	/**
	 * Inicializa um mapa colocando "0" em todas
	 * as sua posições. Um mapa vazio.
	 */
	public void inicializaMapa ()
	{
		Posicao pos = new Posicao(0,0);

		for (int i=0; i < largura; ++i )
		{
			pos.setLinha(i);
			for (int j=0; j < comprimento; ++j)
			{
				pos.setColuna(j);
				mapa.add(pos);
			}
		}
	}

	/**
	 * Pega um elemento no mapa
	 *
	 * @param      posicao   A posição do elemento no mapa
	 *
	 * @return     O elemento do mapa na posição dada.
	 */
	public char getElementoNoMapa (Posicao posicao)
	{
		return posicao.getObjeto();
	}

	/**
	 * Atribui um novo elemento no mapa
	 *
	 * @param      posicao       A posição do elemento
	 * @param      novoElemento  O elemento a ser inserido
	 * na posição informada.
	 */
	public void setElementoNoMapa (Posicao posicao, char novoElemento )
	{
		posicao.setObjeto(novoElemento);
	}

	/**
	 * Pega a quantidade de linhas do mapa
	 *
	 * @return     A quantidade de linhas do mapa.
	 */
	public int getLarguraMapa ()
	{ return largura; }

	/**
	 * Pega a quantidade de colunas do mapa
	 *
	 * @return     A quantidade de colunas do mapa.
	 */
	public int getComprimentoMapa ()
	{ return comprimento; }

	/**
	 * Imprime a situação atual do mapa
	 */
	public void imprimirMapa ()
	{
		int linha =0, coluna = 0;
		String linha_ = new String();

		for (Posicao posicao : mapa )
		{
			linha_ = linha_ + posicao.getObjeto() + " ";
			coluna++;
			if ( coluna == comprimento )
			{
				coluna = 0;
				linha++;
				System.out.println(linha_);
				linha_ = "";
			}

		}
	}
}