Work in progress: Tiling window placement, screen-center-preferring with semi-fixed slots. Not sure I like it. (It looks nice as long as the windows stay equally sized, which they don't.) Settings weren't used anymore, and could be removed. Clean-ups. Changed archive creation to not update an existing archive, but instead create a new archive with a slightly altered filename along-side the existing file. Lock added to safe-guard pipe redirection. A window's Stop/Continue alert now shows the name of the archive in making. I added some code to show and select the archive in Tracker, post-creation, but it does not work reliably, so I've disabled it for now.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34044 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jonas Sundström 2009-11-14 21:49:35 +00:00
parent aece77090d
commit 714236b802
12 changed files with 471 additions and 497 deletions

View File

@ -6,8 +6,6 @@ Application ZipOMatic-Z :
GenericThread.cpp
ZipOMatic.cpp
ZipOMaticActivity.cpp
ZipOMaticMisc.cpp
ZipOMaticSettings.cpp
ZipOMaticWindow.cpp
ZipperThread.cpp

View File

@ -11,7 +11,6 @@
#include <Alert.h>
#include <Roster.h>
#include <Screen.h>
#include <TrackerAddOnAppLaunch.h>
#include "ZipOMaticMisc.h"
@ -31,45 +30,27 @@ main()
ZipOMatic::ZipOMatic()
:
BApplication(ZIPOMATIC_APP_SIG),
fSettings(),
fGotRefs(false),
fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this)),
fWindowFrame(200, 200, 430, 310)
fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this))
{
status_t status = _ReadSettings();
if (status != B_OK)
ErrorMessage("_ReadSettings()", status);
}
ZipOMatic::~ZipOMatic()
{
status_t status = _WriteSettings();
if (status != B_OK)
ErrorMessage("_WriteSettings()", status);
}
void
ZipOMatic::RefsReceived(BMessage* message)
{
message->RemoveName("dir_ref");
entry_ref ref;
if (message->FindRef("refs", &ref) != B_OK) {
if (!IsLaunching())
PostMessage(B_SILENT_RELAUNCH);
return;
}
if (IsLaunching())
if (message->FindRef("refs", &ref) == B_OK) {
_UseExistingOrCreateNewWindow(message);
fGotRefs = true;
BMessage* msg = new BMessage(*message);
_UseExistingOrCreateNewWindow(msg);
} else if (!IsLaunching()) {
PostMessage(B_SILENT_RELAUNCH);
}
}
@ -87,9 +68,6 @@ ZipOMatic::MessageReceived(BMessage* message)
switch (message->what) {
case ZIPPO_WINDOW_QUIT:
{
BRect frame;
if (message->FindRect("frame", &frame) == B_OK)
fWindowFrame = frame;
snooze(200000);
if (CountWindows() == 0)
Quit();
@ -105,7 +83,7 @@ ZipOMatic::MessageReceived(BMessage* message)
if (message->FindInt32("which", &button) == B_OK)
if (button == 0) {
_StopZipping();
} else {
} else {
if (CountWindows() == 0)
Quit();
}
@ -120,7 +98,7 @@ ZipOMatic::MessageReceived(BMessage* message)
bool
ZipOMatic::QuitRequested (void)
ZipOMatic::QuitRequested(void)
{
if (CountWindows() <= 0)
return true;
@ -208,43 +186,42 @@ void
ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message)
{
int32 windowCount = 0;
ZippoWindow* window;
bool foundNonBusyWindow = false;
BWindow* bWindow;
ZippoWindow* zWindow;
BList list;
while (1) {
window = dynamic_cast<ZippoWindow*>(WindowAt(windowCount++));
if (window == NULL)
bWindow = WindowAt(windowCount++);
if (bWindow == NULL)
break;
zWindow = dynamic_cast<ZippoWindow*>(bWindow);
if (zWindow == NULL)
continue;
list.AddItem(zWindow);
if (window->Lock()) {
if (!window->IsZipping()) {
foundNonBusyWindow = true;
if (zWindow->Lock()) {
if (!zWindow->IsZipping()) {
if (message != NULL)
window->PostMessage(message);
window->SetWorkspaces(B_CURRENT_WORKSPACE);
window->Activate();
window->Unlock();
break;
zWindow->PostMessage(message);
zWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
zWindow->Activate();
zWindow->Unlock();
return;
}
window->Unlock();
zWindow->Unlock();
}
}
if (!foundNonBusyWindow)
{
BScreen screen;
fWindowFrame.OffsetBy(screen.Frame().LeftTop());
_CascadeOnFrameCollision(&fWindowFrame);
if(!screen.Frame().Contains(fWindowFrame)) {
fWindowFrame.OffsetTo(screen.Frame().LeftTop());
fWindowFrame.OffsetBy(20,45);
// TODO: replace with CenterOnScreen()
}
ZippoWindow * window = new ZippoWindow(fWindowFrame, message);
window->Show();
if (message) {
zWindow = new ZippoWindow(list);
zWindow->PostMessage(message);
} else {
zWindow = new ZippoWindow(list, true);
}
zWindow->Show();
}
@ -282,93 +259,3 @@ ZipOMatic::_StopZipping()
}
}
status_t
ZipOMatic::_ReadSettings()
{
status_t status = B_OK;
status = fSettings.SetTo("zipomatic.msg");
if (status != B_OK)
return status;
status = fSettings.InitCheck();
if (status != B_OK)
return status;
status = fSettings.InitCheck();
if (status != B_OK)
return status;
status = fSettings.ReadSettings();
if (status != B_OK)
return status;
BRect frame;
status = fSettings.FindRect("frame", &frame);
if (status != B_OK)
return status;
fWindowFrame = frame;
return B_OK;
}
status_t
ZipOMatic::_WriteSettings()
{
status_t status = B_OK;
status = fSettings.InitCheck();
if (status != B_OK)
return status;
status = fSettings.MakeEmpty();
if (status != B_OK)
return status;
status = fSettings.AddRect("frame", fWindowFrame);
if (status != B_OK)
return status;
status = fSettings.WriteSettings();
if (status != B_OK)
return status;
return B_OK;
}
void
ZipOMatic::_CascadeOnFrameCollision(BRect* frame)
{
BWindow* window;
ZippoWindow* zippo;
BList list;
for (int32 i = 0;; i++) {
window = WindowAt(i);
if (window == NULL)
break;
zippo = dynamic_cast<ZippoWindow*>(window);
if (zippo == NULL)
continue;
list.AddItem(zippo);
}
for (int32 i = 0;; i++) {
zippo = static_cast<ZippoWindow*>(list.ItemAt(i));
if (zippo == NULL)
break;
if (zippo->Lock()) {
if (frame->LeftTop() == zippo->Frame().LeftTop())
frame->OffsetBy(20, 20);
zippo->Unlock();
}
}
}

View File

@ -5,9 +5,6 @@
#include <Application.h>
#include <Invoker.h>
#include <Message.h>
#include <Rect.h>
#include "ZipOMaticSettings.h"
class ZipOMatic : public BApplication
@ -22,18 +19,13 @@ public:
virtual bool QuitRequested();
private:
status_t _ReadSettings();
status_t _WriteSettings();
void _CascadeOnFrameCollision(BRect* frame);
void _SilentRelaunch();
void _UseExistingOrCreateNewWindow(BMessage*
message = NULL);
void _StopZipping();
ZippoSettings fSettings;
bool fGotRefs;
BInvoker* fInvoker;
BRect fWindowFrame;
};
#endif // _ZIPOMATIC_H_

View File

@ -88,7 +88,7 @@ Activity::Pulse()
uchar tmp = fPattern.data[7];
for (int j = 7; j > 0; --j)
fPattern.data[j] = fPattern.data[j-1];
fPattern.data[j] = fPattern.data[j - 1];
fPattern.data[0] = tmp;
@ -103,10 +103,6 @@ Activity::Draw(BRect rect)
BRect bitmapRect = fBitmap->Bounds();
if (bitmapRect != viewRect) {
printf("Activity::Draw(): bitmapRect != viewRect\n");
bitmapRect.PrintToStream();
viewRect.PrintToStream();
delete fBitmap;
_CreateBitmap();
}
@ -138,7 +134,7 @@ Activity::_DrawOnBitmap(bool running)
fBitmapView->SetHighColor(color);
// draw the pole
rect.InsetBy(2,2);
rect.InsetBy(2, 2);
fBitmapView->FillRect(rect, fPattern);
// draw frame
@ -198,19 +194,19 @@ Activity::_DrawOnBitmap(bool running)
fBitmapView->SetDrawingMode(B_OP_SUBTRACT);
fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1);
rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1);
rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1);
rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1);
rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect);

View File

@ -1,52 +0,0 @@
/*
* Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jonas Sundström, jonas@kirilla.com
*/
#include "ZipOMaticMisc.h"
#include <string.h>
#include <Debug.h>
status_t
FindAndCreateDirectory(directory_which which, BVolume* volume,
const char* relativePath, BPath* fullPath)
{
BPath path;
status_t status = find_directory(which, &path, true, volume);
if (status != B_OK)
return status;
if (relativePath != NULL) {
path.Append(relativePath);
mode_t mask = umask(0);
umask(mask);
status = create_directory(path.Path(), mask);
if (status != B_OK)
return status;
}
if (fullPath != NULL) {
status = fullPath->SetTo(path.Path());
if (status != B_OK)
return status;
}
return B_OK;
}
void
ErrorMessage(const char* text, int32 status)
{
PRINT(("%s: %s\n", text, strerror(status)));
}

View File

@ -9,12 +9,6 @@
#define ZIPOMATIC_MISC_H
#include <Directory.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Volume.h>
#define ZIPOMATIC_APP_SIG "application/x-vnd.haiku.zip-o-matic"
#define ZIPPO_WINDOW_QUIT 'winq'
@ -24,11 +18,6 @@
#define ZIPPO_TASK_DESCRIPTION 'strt'
#define ZIPPO_LINE_OF_STDOUT 'outp'
status_t FindAndCreateDirectory(directory_which which,
BVolume* volume = NULL, const char* relativePath = NULL,
BPath* fullPath = NULL);
void ErrorMessage(const char* text, int32 status);
#endif // ZIPOMATIC_MISC_H

View File

@ -1,118 +0,0 @@
/*
* Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jonas Sundström, jonas@kirilla.com
*/
// TODO: proper locking <<---------
#include "ZipOMaticSettings.h"
#include <Debug.h>
#include <Directory.h>
#include <File.h>
#include <Path.h>
#include <VolumeRoster.h>
#include "ZipOMaticMisc.h"
ZippoSettings::ZippoSettings()
:
fBaseDir(B_USER_SETTINGS_DIRECTORY)
{
}
ZippoSettings::ZippoSettings(BMessage& message)
:
BMessage(message),
fBaseDir(B_USER_SETTINGS_DIRECTORY)
{
}
ZippoSettings::~ZippoSettings()
{
}
status_t
ZippoSettings::SetTo(const char* filename, BVolume* volume,
directory_which baseDir, const char* relativePath)
{
status_t status = B_OK;
fBaseDir = baseDir;
fRelativePath = relativePath;
fFilename = filename;
if (volume == NULL) {
BVolumeRoster volumeRoster;
volumeRoster.GetBootVolume(&fVolume);
} else {
fVolume = *volume;
}
status = fVolume.InitCheck();
if (status != B_OK)
return status;
return InitCheck();
}
status_t
ZippoSettings::InitCheck()
{
BFile file;
return _GetSettingsFile(&file, B_READ_ONLY | B_CREATE_FILE);
}
status_t
ZippoSettings::ReadSettings()
{
BFile file;
status_t status = _GetSettingsFile(&file, B_READ_ONLY);
if (status != B_OK)
return status;
return Unflatten(&file);
}
status_t
ZippoSettings::WriteSettings()
{
BFile file;
status_t status = _GetSettingsFile(&file, B_WRITE_ONLY | B_ERASE_FILE);
if (status != B_OK)
return status;
return Flatten(&file);
}
status_t
ZippoSettings::_GetSettingsFile(BFile* file, uint32 openMode)
{
BPath path;
status_t status = FindAndCreateDirectory(fBaseDir, &fVolume,
fRelativePath.String(), &path);
if (status != B_OK)
return status;
status = path.Append(fFilename.String());
if (status != B_OK)
return status;
return file->SetTo(path.Path(), openMode);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Jonas Sundström, jonas@kirilla.com
*/
#ifndef _ZIPOMATIC_SETTINGS_H
#define _ZIPOMATIC_SETTINGS_H
#include <FindDirectory.h>
#include <Message.h>
#include <String.h>
#include <Volume.h>
class ZippoSettings : public BMessage {
public:
ZippoSettings();
ZippoSettings(BMessage& message);
~ZippoSettings();
status_t SetTo(const char* filename, BVolume* volume = NULL,
directory_which baseDir =
B_USER_SETTINGS_DIRECTORY,
const char* relativePath = NULL);
status_t InitCheck();
status_t ReadSettings();
status_t WriteSettings();
private:
status_t _GetSettingsFile(BFile* file, uint32 openMode);
BVolume fVolume;
directory_which fBaseDir;
BString fRelativePath;
BString fFilename;
};
#endif // _ZIPOMATIC_SETTINGS_H

View File

@ -21,6 +21,7 @@
#include <LayoutBuilder.h>
#include <Path.h>
#include <Roster.h>
#include <Screen.h>
#include <SeparatorView.h>
#include <String.h>
@ -30,12 +31,13 @@
#include "ZipperThread.h"
ZippoWindow::ZippoWindow(BRect frame, BMessage* refs)
ZippoWindow::ZippoWindow(BList windowList, bool keepOpen)
:
BWindow(frame, "Zip-O-Matic", B_TITLED_WINDOW,
BWindow(BRect(0, 0, 0, 0), "Zip-O-Matic", B_TITLED_WINDOW,
B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE),
fWindowList(windowList),
fThread(NULL),
fWindowGotRefs(false),
fKeepOpen(keepOpen),
fZippingWasStopped(false),
fFileCount(0),
fWindowInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL,
@ -70,10 +72,7 @@ ZippoWindow::ZippoWindow(BRect frame, BMessage* refs)
.End()
.End();
if (refs != NULL) {
fWindowGotRefs = true;
_StartZipping(refs);
}
_FindBestPlacement();
}
@ -88,9 +87,6 @@ ZippoWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_REFS_RECEIVED:
_StartZipping(message);
break;
case B_SIMPLE_DATA:
if (IsZipping()) {
message->what = B_REFS_RECEIVED;
@ -125,8 +121,11 @@ ZippoWindow::MessageReceived(BMessage* message)
case ZIPPO_TASK_DESCRIPTION:
{
BString string;
if (message->FindString("archive_filename", &string) == B_OK)
if (message->FindString("archive_filename", &string) == B_OK) {
fArchiveName = string;
string.Prepend("Creating archive: ");
fArchiveNameView->SetText(string.String());
}
break;
}
@ -202,11 +201,14 @@ ZippoWindow::QuitRequested()
fThread->SuspendExternalZip();
fActivityView->Pause();
BAlert* alert = new BAlert("Stop or Continue",
"Are you sure you want to stop creating this archive?", "Stop",
BString message;
message << "Are you sure you want to stop creating this archive?\n\n";
message << "Filename: " << fArchiveName.String() << "\n";
BAlert* alert = new BAlert(NULL, message.String(), "Stop",
"Continue", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go(fWindowInvoker);
return false;
}
}
@ -261,7 +263,155 @@ ZippoWindow::IsZipping()
void
ZippoWindow::_CloseWindowOrKeepOpen()
{
if (fWindowGotRefs)
if (!fKeepOpen)
PostMessage(B_QUIT_REQUESTED);
}
void
ZippoWindow::_FindBestPlacement()
{
CenterOnScreen();
BScreen screen;
BRect centeredRect = Frame();
BRect tryRect = centeredRect;
BList tryRectList;
if (!screen.Frame().Contains(centeredRect))
return;
// build a list of possible locations
tryRectList.AddItem(new BRect(centeredRect));
// up and left
direction primaryDirection = up;
while (true) {
_OffsetRect(&tryRect, primaryDirection);
if (!screen.Frame().Contains(tryRect))
_OffscreenBounceBack(&tryRect, &primaryDirection, left);
if (!screen.Frame().Contains(tryRect))
break;
tryRectList.AddItem(new BRect(tryRect));
}
// down and right
primaryDirection = down;
tryRect = centeredRect;
while (true) {
_OffsetRect(&tryRect, primaryDirection);
if (!screen.Frame().Contains(tryRect))
_OffscreenBounceBack(&tryRect, &primaryDirection, right);
if (!screen.Frame().Contains(tryRect))
break;
tryRectList.AddItem(new BRect(tryRect));
}
// remove rects that overlap an existing window
for (int32 i = 0;; i++) {
BWindow* win = static_cast<BWindow*>(fWindowList.ItemAt(i));
if (win == NULL)
break;
ZippoWindow* window = dynamic_cast<ZippoWindow*>(win);
if (window == NULL)
continue;
if (window == this)
continue;
if (window->Lock()) {
BRect frame = window->Frame();
for (int32 m = 0;; m++) {
BRect* rect = static_cast<BRect*>(tryRectList.ItemAt(m));
if (rect == NULL)
break;
if (frame.Intersects(*rect)) {
tryRectList.RemoveItem(m);
delete rect;
m--;
}
}
window->Unlock();
}
}
// find nearest rect
bool gotRect = false;
BRect nearestRect(0, 0, 0, 0);
while (true) {
BRect* rect = static_cast<BRect*>(tryRectList.RemoveItem((int32)0));
if (rect == NULL)
break;
nearestRect = _NearestRect(centeredRect, nearestRect, *rect);
gotRect = true;
delete rect;
}
if (gotRect)
MoveTo(nearestRect.LeftTop());
}
void
ZippoWindow::_OffsetRect(BRect* rect, direction whereTo)
{
float width = rect->Width();
float height = rect->Height();
switch (whereTo) {
case up:
rect->OffsetBy(0, -(height * 1.5));
break;
case down:
rect->OffsetBy(0, height * 1.5);
break;
case left:
rect->OffsetBy(-(width * 1.5), 0);
break;
case right:
rect->OffsetBy(width * 1.5, 0);
break;
}
}
void
ZippoWindow::_OffscreenBounceBack(BRect* rect, direction* primaryDirection,
direction secondaryDirection)
{
if (*primaryDirection == up) {
*primaryDirection = down;
} else {
*primaryDirection = up;
}
_OffsetRect(rect, *primaryDirection);
_OffsetRect(rect, secondaryDirection);
}
BRect
ZippoWindow::_NearestRect(BRect goalRect, BRect a, BRect b)
{
double aSum = fabs(goalRect.left - a.left) + fabs(goalRect.top - a.top);
double bSum = fabs(goalRect.left - b.left) + fabs(goalRect.top - b.top);
if (aSum < bSum)
return a;
else
return b;
}

View File

@ -3,6 +3,8 @@
#include <Button.h>
#include <List.h>
#include <Rect.h>
#include <StringView.h>
#include <Window.h>
@ -10,10 +12,19 @@
#include "ZipperThread.h"
enum direction {
up,
down,
left,
right
};
class ZippoWindow : public BWindow
{
public:
ZippoWindow(BRect frame, BMessage* refs = NULL);
ZippoWindow(BList windowList,
bool keepOpen = false);
~ZippoWindow();
virtual void MessageReceived(BMessage* message);
@ -27,14 +38,24 @@ private:
void _StartZipping(BMessage* message);
void _CloseWindowOrKeepOpen();
void _FindBestPlacement();
void _OffsetRect(BRect* rect, direction whereTo);
void _OffscreenBounceBack(BRect* rect,
direction* primaryDirection,
direction secondaryDirection);
BRect _NearestRect(BRect goalRect, BRect a, BRect b);
BList fWindowList;
Activity* fActivityView;
BStringView* fArchiveNameView;
BStringView* fZipOutputView;
BButton* fStopButton;
ZipperThread* fThread;
BString fArchiveName;
bool fWindowGotRefs;
bool fKeepOpen;
bool fZippingWasStopped;
int32 fFileCount;

View File

@ -12,9 +12,11 @@
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <FindDirectory.h>
#include <Locker.h>
#include <Message.h>
#include <Path.h>
#include <Volume.h>
@ -34,9 +36,6 @@ ZipperThread::ZipperThread(BMessage* refsMessage, BWindow* window)
fOutputFile(NULL)
{
fThreadDataStore = new BMessage(*refsMessage);
// leak?
// prevents bug with B_SIMPLE_DATA
// (drag&drop messages)
}
@ -48,9 +47,6 @@ ZipperThread::~ZipperThread()
status_t
ZipperThread::ThreadStartup()
{
BString archiveName = "Archive.zip";
// do all refs have the same parent dir?
type_code type = B_REF_TYPE;
int32 refCount = 0;
entry_ref ref;
@ -58,23 +54,17 @@ ZipperThread::ThreadStartup()
bool sameFolder = true;
status_t status = fThreadDataStore->GetInfo("refs", &type, &refCount);
if (status != B_OK)
return status;
if (status != B_OK || refCount < 1) {
_SendMessageToWindow(ZIPPO_THREAD_EXIT_ERROR);
Quit();
return B_ERROR;
}
for (int index = 0; index < refCount; index++) {
fThreadDataStore->FindRef("refs", index, &ref);
if (index > 0) {
BEntry entry(&ref);
if (entry.IsSymLink()) {
entry.SetTo(&ref, true);
entry_ref target;
entry.GetRef(&target);
if (lastRef.directory != target.directory) {
sameFolder = false;
break;
}
} else if (lastRef.directory != ref.directory) {
if (lastRef.directory != ref.directory) {
sameFolder = false;
break;
}
@ -82,8 +72,27 @@ ZipperThread::ThreadStartup()
lastRef = ref;
}
// change active dir
if (sameFolder) {
entry_ref dirRef;
bool gotDirRef = false;
status = fThreadDataStore->FindRef("dir_ref", 0, &dirRef);
if (status == B_OK) {
BEntry dirEntry(&dirRef);
BNode dirNode(&dirRef);
if (dirEntry.InitCheck() == B_OK
&& dirEntry.Exists()
&& dirNode.InitCheck() == B_OK
&& dirNode.IsDirectory())
gotDirRef = true;
}
if (gotDirRef) {
BEntry entry(&dirRef);
BPath path;
entry.GetPath(&path);
chdir(path.Path());
} else if (sameFolder) {
BEntry entry(&lastRef);
BPath path;
entry.GetParent(&entry);
@ -95,10 +104,28 @@ ZipperThread::ThreadStartup()
chdir(path.Path());
}
// archive filename
if (refCount == 1) {
BString archiveName;
if (refCount > 1)
archiveName = "Archive";
else
archiveName = lastRef.name;
archiveName += ".zip";
int index = 1;
for (;; index++) {
BString tryName = archiveName;
if (index != 1)
tryName << " " << index;
tryName << ".zip";
BEntry entry(tryName.String());
if (!entry.Exists()) {
archiveName = tryName;
entry.GetRef(&fOutputEntryRef);
break;
}
}
int32 argc = refCount + 3;
@ -108,15 +135,12 @@ ZipperThread::ThreadStartup()
argv[1] = strdup("-ry");
argv[2] = strdup(archiveName.String());
// files to zip
for (int index = 0; index < refCount; index++) {
fThreadDataStore->FindRef("refs", index, &ref);
if (sameFolder) {
// just the file name
if (gotDirRef || sameFolder) {
argv[3 + index] = strdup(ref.name);
} else {
// full path
BPath path(&ref);
BString file = path.Path();
argv[3 + index] = strdup(path.Path());
@ -138,8 +162,6 @@ ZipperThread::ThreadStartup()
if (fOutputFile == NULL)
return errno;
archiveName.Prepend("Creating archive: ");
_SendMessageToWindow(ZIPPO_TASK_DESCRIPTION, "archive_filename",
archiveName.String());
_SendMessageToWindow(ZIPPO_LINE_OF_STDOUT, "zip_output",
@ -152,8 +174,6 @@ ZipperThread::ThreadStartup()
status_t
ZipperThread::ExecuteUnit()
{
// read output from /bin/zip
// send it to window
char buffer[4096];
char* output = fgets(buffer, sizeof(buffer) - 1, fOutputFile);
@ -185,6 +205,8 @@ ZipperThread::ThreadShutdown()
close(fStdOut);
close(fStdErr);
// _SelectInTracker();
return B_OK;
}
@ -192,7 +214,6 @@ ZipperThread::ThreadShutdown()
void
ZipperThread::ThreadStartupFailed(status_t status)
{
ErrorMessage("ZipperThread::ThreadStartupFailed() \n", status);
Quit();
}
@ -200,8 +221,6 @@ ZipperThread::ThreadStartupFailed(status_t status)
void
ZipperThread::ExecuteUnitFailed(status_t status)
{
ErrorMessage("ZipperThread::ExecuteUnitFailed() \n", status);
if (status == EOF) {
// thread has finished, been quit or killed, we don't know
_SendMessageToWindow(ZIPPO_THREAD_EXIT);
@ -217,7 +236,8 @@ ZipperThread::ExecuteUnitFailed(status_t status)
void
ZipperThread::ThreadShutdownFailed(status_t status)
{
ErrorMessage("ZipperThread::ThreadShutdownFailed() \n", status);
fprintf(stderr, "ZipperThread::ThreadShutdownFailed(): %s\n",
strerror(status));
}
@ -234,68 +254,78 @@ thread_id
ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out,
int& err, const char** envp)
{
// This function was originally written by Peter Folk <pfolk@uni.uiuc.edu>
// and published in the BeDevTalk FAQ
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
static BLocker lock;
thread_id thread;
if (lock.Lock()) {
// This function was originally written by Peter Folk
// <pfolk@uni.uiuc.edu> and published in the BeDevTalk FAQ
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
// Save current FDs
int oldIn = dup(STDIN_FILENO);
int oldOut = dup(STDOUT_FILENO);
int oldErr = dup(STDERR_FILENO);
thread_id thread;
int inPipe[2], outPipe[2], errPipe[2];
// Save current FDs
int oldIn = dup(STDIN_FILENO);
int oldOut = dup(STDOUT_FILENO);
int oldErr = dup(STDERR_FILENO);
// Create new pipe FDs as stdin, stdout, stderr
if (pipe(inPipe) < 0)
goto err1;
if (pipe(outPipe) < 0)
goto err2;
if (pipe(errPipe) < 0)
goto err3;
int inPipe[2], outPipe[2], errPipe[2];
errno = 0;
// Create new pipe FDs as stdin, stdout, stderr
if (pipe(inPipe) < 0)
goto err1;
if (pipe(outPipe) < 0)
goto err2;
if (pipe(errPipe) < 0)
goto err3;
// replace old stdin/stderr/stdout
dup2(inPipe[0], STDIN_FILENO);
close(inPipe[0]);
dup2(outPipe[1], STDOUT_FILENO);
close(outPipe[1]);
dup2(errPipe[1], STDERR_FILENO);
close(errPipe[1]);
errno = 0;
if (errno == 0) {
in = inPipe[1]; // Write to in, appears on cmd's stdin
out = outPipe[0]; // Read from out, taken from cmd's stdout
err = errPipe[0]; // Read from err, taken from cmd's stderr
// replace old stdin/stderr/stdout
dup2(inPipe[0], STDIN_FILENO);
close(inPipe[0]);
dup2(outPipe[1], STDOUT_FILENO);
close(outPipe[1]);
dup2(errPipe[1], STDERR_FILENO);
close(errPipe[1]);
// execute command
thread = load_image(argc, argv, envp);
if (errno == 0) {
in = inPipe[1]; // Write to in, appears on cmd's stdin
out = outPipe[0]; // Read from out, taken from cmd's stdout
err = errPipe[0]; // Read from err, taken from cmd's stderr
// execute command
thread = load_image(argc, argv, envp);
} else {
thread = errno;
}
// Restore old FDs
dup2(oldIn, STDIN_FILENO);
close(oldIn);
dup2(oldOut, STDOUT_FILENO);
close(oldOut);
dup2(oldErr, STDERR_FILENO);
close(oldErr);
lock.Unlock();
return thread;
err3:
close(outPipe[0]);
close(outPipe[1]);
err2:
close(inPipe[0]);
close(inPipe[1]);
err1:
close(oldIn);
close(oldOut);
close(oldErr);
lock.Unlock();
return errno;
} else {
thread = errno;
return B_ERROR;
}
// Restore old FDs
dup2(oldIn, STDIN_FILENO);
close(oldIn);
dup2(oldOut, STDOUT_FILENO);
close(oldOut);
dup2(oldErr, STDERR_FILENO);
close(oldErr);
return thread;
err3:
close(outPipe[0]);
close(outPipe[1]);
err2:
close(inPipe[0]);
close(inPipe[1]);
err1:
close(oldIn);
close(oldOut);
close(oldErr);
return errno;
}
@ -366,3 +396,123 @@ ZipperThread::WaitOnExternalZip()
return status;
}
status_t
ZipperThread::_SelectInTracker(int32 tryNumber)
{
// work in progress - unreliable - not ready to be used
entry_ref parentRef;
BEntry entry(&fOutputEntryRef);
if (!entry.Exists())
return B_FILE_NOT_FOUND;
entry.GetParent(&entry);
entry.GetRef(&parentRef);
BMessenger trackerMessenger("application/x-vnd.Be-TRAK");
if (!trackerMessenger.IsValid())
return B_ERROR;
BMessage request;
BMessage reply;
status_t status;
if (tryNumber == 0) {
request.MakeEmpty();
request.what = B_REFS_RECEIVED;
request.AddRef("refs", &parentRef);
trackerMessenger.SendMessage(&request, &reply);
}
if (tryNumber > 20)
return B_ERROR;
snooze(200000);
// find out the number of Tracker windows
request.MakeEmpty();
request.what = B_COUNT_PROPERTIES;
request.AddSpecifier("Window");
reply.MakeEmpty();
status = trackerMessenger.SendMessage(&request, &reply);
if (status != B_OK)
return status;
int32 windowCount;
status = reply.FindInt32("result", &windowCount);
if (status != B_OK)
return status;
// find a likely parent window
bool foundWindow = false;
int32 index = 0;
for (; index < windowCount; index++) {
request.MakeEmpty();
request.what = B_GET_PROPERTY;
request.AddSpecifier("Path");
request.AddSpecifier("Poses");
request.AddSpecifier("Window", index);
reply.MakeEmpty();
status = trackerMessenger.SendMessage(&request, &reply);
if (status != B_OK)
continue;
entry_ref windowRef;
status = reply.FindRef("result", &windowRef);
if (status != B_OK)
continue;
if (windowRef == parentRef) {
foundWindow = true;
break;
}
}
if (!foundWindow)
return _SelectInTracker(tryNumber + 1);
// find entry_ref in window - a newly opened window might
// be filling and the entry_ref perhaps not there yet?
request.MakeEmpty();
request.what = B_GET_PROPERTY;
request.AddSpecifier("Entry");
request.AddSpecifier("Poses");
request.AddSpecifier("Window", index);
reply.MakeEmpty();
status = trackerMessenger.SendMessage(&request, &reply);
if (status != B_OK)
return _SelectInTracker(tryNumber + 1);
bool foundRef = false;
entry_ref ref;
for (int32 m = 0;; m++) {
status = reply.FindRef("result", m, &ref);
if (status != B_OK)
break;
if (ref == fOutputEntryRef)
foundRef = true;
}
// if entry_ref not found in window, start over
if (!foundRef)
return _SelectInTracker(tryNumber + 1);
// select archive file in Tracker window
request.MakeEmpty();
request.what = B_SET_PROPERTY;
request.AddRef("data", &fOutputEntryRef);
request.AddSpecifier("Selection");
request.AddSpecifier("Poses");
request.AddSpecifier("Window", index);
reply.MakeEmpty();
status = trackerMessenger.SendMessage(&request, &reply);
return status;
}

View File

@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <Entry.h>
#include <Message.h>
#include <Messenger.h>
#include <String.h>
@ -48,15 +49,18 @@ private:
const char** envp = (const char**)environ);
void _SendMessageToWindow(uint32 what,
const char* name = NULL,
const char* name = NULL,
const char* value = NULL);
status_t _SelectInTracker(int32 tryNumber = 0);
BMessenger fWindowMessenger;
thread_id fZipProcess;
int fStdIn;
int fStdOut;
int fStdErr;
FILE* fOutputFile;
entry_ref fOutputEntryRef;
};
#endif // _ZIPPER_THREAD_H