version 1.0 of Jonas Sundstrom's ZipOMatic app/add-on

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4282 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shatty 2003-08-16 00:57:12 +00:00
parent c0ecc31328
commit 926f5ddfbe
22 changed files with 2261 additions and 0 deletions

View File

@ -84,4 +84,5 @@ SubInclude OBOS_TOP src add-ons media ;
SubInclude OBOS_TOP src add-ons print ;
SubInclude OBOS_TOP src add-ons translators ;
SubInclude OBOS_TOP src add-ons decorators ;
SubInclude OBOS_TOP src add-ons tracker ;

View File

@ -0,0 +1,4 @@
SubDir OBOS_TOP src add-ons tracker ;
SubInclude OBOS_TOP src add-ons tracker zipomatic ;

View File

@ -0,0 +1,386 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <GenericThread.h>
GenericThread::GenericThread(const char * a_thread_name, int32 a_priority, BMessage * a_message)
:
m_thread_data_store (a_message),
m_thread_id (spawn_thread (private_thread_function, a_thread_name, a_priority, this)),
m_execute_unit (create_sem(1, "m_execute_unit")),
m_quit_requested (false),
m_thread_is_paused (false)
{
if (m_thread_data_store == NULL)
m_thread_data_store = new BMessage();
}
GenericThread::~GenericThread()
{
kill_thread(m_thread_id);
delete_sem(m_execute_unit);
}
status_t
GenericThread::ThreadFunction (void)
{
status_t status = B_OK;
status = ThreadStartup(); // Subclass and override this function
if (status != B_OK)
{
ThreadStartupFailed (status);
return (status);
// is this the right thing to do?
}
while(1)
{
if (HasQuitBeenRequested())
{
status = ThreadShutdown(); // Subclass and override this function
if (status != B_OK)
{
ThreadShutdownFailed (status);
return (status);
// what do we do?
}
delete this; // destructor
}
BeginUnit();
status = ExecuteUnit(); // Subclass and override
if (status != B_OK)
ExecuteUnitFailed (status); // Subclass and override
EndUnit();
}
return (B_OK);
}
status_t
GenericThread::ThreadStartup (void)
{
// This function is virtual.
// Subclass and override this function.
return B_OK;
}
status_t
GenericThread::ExecuteUnit (void)
{
// This function is virtual.
// You would normally subclass and override this function
// as it will provide you with Pause and Quit functionality
// thanks to the unit management done by GenericThread::ThreadFunction()
return B_OK;
}
status_t
GenericThread::ThreadShutdown (void)
{
// This function is virtual.
// Subclass and override this function.
return B_OK;
}
void
GenericThread::ThreadStartupFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
Quit();
}
void
GenericThread::ExecuteUnitFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
Quit();
}
void
GenericThread::ThreadShutdownFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
// (is this good default behaviour?)
}
status_t
GenericThread::Start (void)
{
status_t status = B_OK;
if (IsPaused())
{
status = release_sem (m_execute_unit);
if (status != B_OK)
return status;
m_thread_is_paused = false;
}
status = resume_thread (m_thread_id);
return status;
}
int32
GenericThread::private_thread_function (void * a_simple_thread_ptr)
{
status_t status = B_OK;
status = ((GenericThread *) a_simple_thread_ptr)-> ThreadFunction();
return (status);
}
BMessage *
GenericThread::GetDataStore (void)
{
return (m_thread_data_store);
}
void
GenericThread::SetDataStore (BMessage * a_message)
{
m_thread_data_store = a_message;
}
status_t
GenericThread::Pause (bool a_do_block, bigtime_t a_timeout)
{
status_t status = B_OK;
if (a_do_block)
status = acquire_sem(m_execute_unit);
// thread will wait on semaphore
else
status = acquire_sem_etc(m_execute_unit, 1, B_RELATIVE_TIMEOUT, a_timeout);
// thread will timeout
if (status == B_OK)
{
m_thread_is_paused = true;
return (B_OK);
}
return status;
}
void
GenericThread::Quit (void)
{
m_quit_requested = true;
}
bool
GenericThread::HasQuitBeenRequested (void)
{
return (m_quit_requested);
}
bool
GenericThread::IsPaused (void)
{
return (m_thread_is_paused);
}
status_t
GenericThread::Suspend (void)
{
return (suspend_thread(m_thread_id));
}
status_t
GenericThread::Resume (void)
{
release_sem(m_execute_unit); // to counteract Pause()
m_thread_is_paused = false;
return (resume_thread(m_thread_id)); // to counteract Suspend()
}
status_t
GenericThread::Kill (void)
{
return (kill_thread(m_thread_id));
}
void
GenericThread::ExitWithReturnValue (status_t a_return_value)
{
exit_thread(a_return_value);
}
status_t
GenericThread::SetExitCallback (void (*a_callback)(void*), void * a_data)
{
return (on_exit_thread(a_callback, a_data));
}
status_t
GenericThread::WaitForThread (status_t * a_exit_value)
{
return (wait_for_thread(m_thread_id, a_exit_value));
}
status_t
GenericThread::Rename (char * a_name)
{
return (rename_thread(m_thread_id, a_name));
}
status_t
GenericThread::SendData (int32 a_code, void * a_buffer, size_t a_buffer_size)
{
return (send_data(m_thread_id, a_code, a_buffer, a_buffer_size));
}
int32
GenericThread::ReceiveData (thread_id * a_sender, void * a_buffer, size_t a_buffer_size)
{
return (receive_data(a_sender, a_buffer, a_buffer_size));
}
bool
GenericThread::HasData (void)
{
return (has_data(m_thread_id));
}
status_t
GenericThread::SetPriority (int32 a_new_priority)
{
return (set_thread_priority(m_thread_id, a_new_priority));
}
void
GenericThread::Snooze (bigtime_t a_microseconds)
{
Suspend();
snooze(a_microseconds);
Resume();
}
void
GenericThread::SnoozeUntil (bigtime_t a_microseconds, int a_timebase)
{
Suspend();
snooze_until(a_microseconds, a_timebase);
Resume();
}
status_t
GenericThread::GetInfo (thread_info * a_thread_info)
{
return (get_thread_info(m_thread_id, a_thread_info));
}
thread_id
GenericThread::GetThread (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.thread);
}
team_id
GenericThread::GetTeam (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.team);
}
char *
GenericThread::GetName (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.name);
}
thread_state
GenericThread::GetState (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.state);
}
sem_id
GenericThread::GetSemaphore (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.sem);
}
int32
GenericThread::GetPriority (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.priority);
}
bigtime_t
GenericThread::GetUserTime (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.user_time);
}
bigtime_t
GenericThread::GetKernelTime (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.kernel_time);
}
void *
GenericThread::GetStackBase (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.stack_base);
}
void *
GenericThread::GetStackEnd (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.stack_end);
}
void
GenericThread::BeginUnit (void)
{
acquire_sem(m_execute_unit); // thread can not be paused until it releases semaphore
}
void
GenericThread::EndUnit (void)
{
release_sem(m_execute_unit); // thread can now be paused
}

View File

@ -0,0 +1,83 @@
#ifndef __GENERIC_THREAD_H__
#define __GENERIC_THREAD_H__
#include <OS.h>
#include <Message.h>
class GenericThread
{
public:
GenericThread (const char * a_thread_name = "generic_thread", int32 a_priority = B_NORMAL_PRIORITY, BMessage * a_message = NULL);
virtual ~GenericThread (void);
BMessage * GetDataStore (void);
void SetDataStore (BMessage * a_message);
status_t Start (void);
status_t Pause (bool a_do_block = TRUE, bigtime_t a_timeout = 0);
void Quit (void);
bool IsPaused (void);
bool HasQuitBeenRequested (void);
status_t Suspend (void);
status_t Resume (void);
status_t Kill (void);
void ExitWithReturnValue (status_t a_return_value);
status_t SetExitCallback (void (* a_callback)(void *), void * a_data);
status_t WaitForThread (status_t * a_exit_value);
status_t Rename (char * a_name);
status_t SendData (int32 a_code, void * a_buffer, size_t a_buffer_size);
int32 ReceiveData (thread_id * a_sender, void * a_buffer, size_t a_buffer_size);
bool HasData (void);
status_t SetPriority (int32 a_new_priority);
void Snooze (bigtime_t a_microseconds);
void SnoozeUntil (bigtime_t a_microseconds, int a_timebase = B_SYSTEM_TIMEBASE);
status_t GetInfo (thread_info * a_thread_info);
thread_id GetThread (void);
team_id GetTeam (void);
char * GetName (void);
thread_state GetState (void);
sem_id GetSemaphore (void);
int32 GetPriority (void);
bigtime_t GetUserTime (void);
bigtime_t GetKernelTime (void);
void * GetStackBase (void);
void * GetStackEnd (void);
protected:
virtual status_t ThreadFunction (void);
virtual status_t ThreadStartup (void);
virtual status_t ExecuteUnit (void);
virtual status_t ThreadShutdown (void);
virtual void ThreadStartupFailed (status_t a_status);
virtual void ExecuteUnitFailed (status_t a_status);
virtual void ThreadShutdownFailed (status_t a_status);
void BeginUnit (void); // acquire m_execute_cycle
void EndUnit (void); // release m_execute_cycle
BMessage * m_thread_data_store;
private:
static status_t private_thread_function (void * a_simple_thread_ptr);
thread_id m_thread_id;
sem_id m_execute_unit; // acq./relase within tread_function.. For Pause()
bool m_quit_requested;
bool m_thread_is_paused;
};
#endif

View File

@ -0,0 +1,19 @@
SubDir OBOS_TOP src add-ons tracker zipomatic ;
AddResources ZipOMatic-Z :
ZipOMatic.rdef ZipOMatic.icons.rdef ZipOMatic.version.rdef
;
App ZipOMatic-Z :
GenericThread.cpp
ZipOMatic.cpp
ZipOMaticActivity.cpp
ZipOMaticMisc.cpp
ZipOMaticSettings.cpp
ZipOMaticView.cpp
ZipOMaticWindow.cpp
ZipOMaticZipper.cpp
;
MakeLocate ZipOMatic-Z : [ FDirName $(OBOS_ADDON_DIR) Tracker ] ;
LinkSharedOSLibs ZipOMatic-Z : be tracker ;

View File

@ -0,0 +1,187 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <TrackerAddOn.h>
#include <Roster.h>
#include <Debug.h>
#include <ZipOMatic.h>
#include <ZipOMaticMisc.h>
#include <ZipOMaticWindow.h>
extern "C" void
process_refs(entry_ref dir_ref, BMessage * msg, void *)
{
msg->AddRef("dir_ref", & dir_ref);
status_t status = B_OK;
type_code ref_type = B_REF_TYPE;
int32 ref_count = 0;
status = msg->GetInfo("refs", & ref_type, & ref_count);
if (status != B_OK || ref_count < 1)
be_roster->Launch (ZIPOMATIC_APP_SIG);
else
be_roster->Launch (ZIPOMATIC_APP_SIG, msg );
}
int main()
{
ZipOMatic app;
app.Run();
return (0);
}
ZipOMatic::ZipOMatic (void)
: BApplication (ZIPOMATIC_APP_SIG),
m_got_refs (false)
{
PRINT(("ZipOMatic::ZipOMatic()\n"));
// void
}
ZipOMatic::~ZipOMatic (void)
{
PRINT(("ZipOMatic::~ZipOMatic()\n"));
fflush(stdout);
}
void
ZipOMatic::RefsReceived (BMessage * a_message)
{
PRINT(("ZipOMatic::RefsReceived()\n"));
if (IsLaunching())
m_got_refs = true;
BMessage * msg = new BMessage (* a_message);
UseExistingOrCreateNewWindow(msg);
}
void
ZipOMatic::ReadyToRun (void)
{
PRINT(("ZipOMatic::ReadyToRun()\n"));
if (m_got_refs)
{
// nothing - wait on window(s) to finish
}
else
UseExistingOrCreateNewWindow();
}
void
ZipOMatic::MessageReceived (BMessage * a_message)
{
PRINT(("ZipOMatic::MessageReceived()\n"));
switch(a_message->what)
{
case ZIPPO_WINDOW_QUIT:
snooze (200000);
if (CountWindows() == 0)
Quit();
break;
case B_SILENT_RELAUNCH:
SilentRelaunch();
break;
default: BApplication::MessageReceived(a_message); break;
}
}
bool
ZipOMatic::QuitRequested (void)
{
// intelligent (?) closing of the windows
//
// overriding BApplication::QuitRequested();
if (CountWindows() <= 0)
return true;
BList window_list (5);
int32 window_count = 0;
BWindow * window;
// build list of windows
while (1)
{
window = WindowAt(window_count++);
if (window == NULL)
break;
window_list.AddItem(window);
}
// ask windows to quit
while (1)
{
window = (BWindow *) window_list.RemoveItem(int32(0));
if (window == NULL)
break;
if (window->Lock())
{
window->PostMessage(B_QUIT_REQUESTED);
window->Unlock();
}
}
PRINT(("CountWindows(): %ld\n", CountWindows()));
if (CountWindows() <= 0)
return true;
return false; // default: stay alive
}
void
ZipOMatic::SilentRelaunch (void)
{
UseExistingOrCreateNewWindow();
}
void
ZipOMatic::UseExistingOrCreateNewWindow (BMessage * a_message)
{
int32 window_count = 0;
ZippoWindow * window;
bool found_non_busy_window = false;
while (1)
{
window = dynamic_cast<ZippoWindow *>(WindowAt(window_count++));
if (window == NULL)
break;
if (window->Lock())
{
if (! window->IsZipping())
{
found_non_busy_window = true;
if (a_message != NULL)
window->PostMessage(a_message);
window->Activate();
window->Unlock();
break;
}
window->Unlock();
}
}
if (! found_non_busy_window)
{
ZippoWindow * m_window = new ZippoWindow(a_message);
m_window->Show();
}
}

View File

@ -0,0 +1,28 @@
#ifndef _ZIPOMATIC_H_
#define _ZIPOMATIC_H_
#include <Application.h>
#include <Message.h>
class ZipOMatic : public BApplication
{
public:
ZipOMatic (void);
~ZipOMatic (void);
virtual void ReadyToRun (void);
virtual void RefsReceived (BMessage * a_message);
virtual void MessageReceived (BMessage * a_message);
virtual bool QuitRequested (void);
void SilentRelaunch (void);
void UseExistingOrCreateNewWindow (BMessage * a_message = NULL);
private:
bool m_got_refs;
};
#endif // _ZIPOMATIC_H_

View File

@ -0,0 +1,59 @@
/*
** ZipOMatic.icons.rdef
**
*/
resource large_icon array {
$"FFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFF00FAFAFAFA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFF00FAFAFAFAFAFA5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFF00FAFAFAFAFA5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFF003FF9F9FA5D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFF007D3FF9F9F95D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFF007D7D3FF9F9F95D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FF003F3F7D3FF9F9F95D5D5D00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFF00F93F3FF9F9F95D5D5D0000D9D90000FFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFF00F9F93FF9F9F95D5D7D7D7D0000D9D90000FFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFF00F9F9F9F9F93F3F7D7D7D00D9D9D9D9D90000FFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFF00F9F9F9F9F9F93F7D00D9D9D9D9D9D900D90000FFFFFFFFFFFFFFFF"
$"FFFFFFFF00F9F9F9F9F9F90000D9D900D9D9D900D9D9D9D90000FFFFFFFFFFFF"
$"FFFFFFFFFF00F9F9F9F900D9D9D9D900D9D900D9D9D9D9D9D9D90000FFFFFFFF"
$"FFFFFFFF00D900F90000000000000000D900D9D9D9D9D9D9D9D9D9D900FFFFFF"
$"FFFFFF00D9D9D900D9000000D9D9000000D9D9D9D9D9D9D9D9D9D9D9D900FFFF"
$"FFFF00D9D9D9D9D9D900D9D90000D900000000000000D9D9D9D9D9D9D9D900FF"
$"FF00D9D9D9D9D9D9D9D9000000D9000000D9D9D9D9D900D9D9D9D9D9D98300FF"
$"FF00D9D9D9D9D9D9D9D9D9D9D900D9D90000D9D90000D9D9D9D9D9D9838300FF"
$"00D9D9D9D9D9D9D9D9D9D9D900D9D900D900000000D9D9D9D9D9D983838300FF"
$"00D9D9D9D9D9D9D9D9D9D900D9D9D900D9D9D9D9D90000D9D9D98383838300FF"
$"00D9D9D9D9D9D9D9D9D900D9D9D9D9D9D9D9D9D9D9D9D900008383838300FFFF"
$"FF00D9D9D9D9D9D9D900D9D9D9D9D9D9D9D9D9D9D9D9D9D90083838300FFFFFF"
$"FFFF0000D9D9D9D9D901D9D9D9D9D9D9D9D9D9D9D9D9D98300838300FFFFFFFF"
$"FFFFFFFF0000D9D9D901D9D9D9D9D9D9D9D9D9D9D9D98383008300FFFFFFFFFF"
$"FFFFFFFFFFFF0000D900D9D9D9D9D9D9D9D9D9D9D98383830000FFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFF0000D9D9D9D9D9D9D9D9D9D98383838300FFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFF0000D9D9D9D9D9D9D98383838301FFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFF0000D9D9D9D98383838301FFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000D9D983830100FFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource mini_icon array {
$"FFFFFFFF000000FFFFFFFFFFFFFFFFFF"
$"FFFFFF00FAFA5D00FFFFFFFFFFFFFFFF"
$"FFFF003F3F3F5D00FFFFFFFFFFFFFFFF"
$"FFFF003FF9F95D0000FFFFFFFFFFFFFF"
$"FF00003FF9F95D00D90000FFFFFFFFFF"
$"007D003FF9F95D7D00D9000000FFFFFF"
$"3F00F9F9F9F93F008300D9D9D90000FF"
$"3F0000F9F9F90000000000D9D9D98300"
$"00D9D900F900000083D9D900D93F8300"
$"00D93FD900830000000000D93F838300"
$"00D9D9D9D900D900D9D9D901008300FF"
$"0000D9D9003FD900D9D93F830000FFFF"
$"FFFF000000D9D93FD93F838300FFFFFF"
$"FFFFFFFF0000D9D9D9838301FFFFFFFF"
$"FFFFFFFFFFFF0000D98301FFFFFFFFFF"
$"FFFFFFFFFFFFFFFF0000FFFFFFFFFFFF"
};

View File

@ -0,0 +1,12 @@
/*
** ZipOMatic.rdef
**
*/
resource app_signature "application/x-vnd.obos.zip-o-matic";
resource app_flags 0x00000000;
resource file_types message {
"types" = "application/octet-stream"
};

View File

@ -0,0 +1,20 @@
/*
** ZipOMatic.version.rdef
**
*/
resource app_version {
major = 1,
middle = 0,
minor = 0,
/* 0 = development 1 = alpha 2 = beta
3 = gamma 4 = golden master 5 = final */
variety = 0,
internal = 1,
short_info = "R1.0.0d1",
long_info = "OpenBeOS 1.0.0d1 ©2003 OpenBeOS Project"
};

View File

@ -0,0 +1,232 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <ZipOMaticActivity.h>
Activity::Activity (BRect a_rect, const char * a_name, uint32 a_resizing_mode, uint32 a_flags)
: BBox (a_rect, a_name, a_resizing_mode, a_flags),
m_is_running (false),
m_barberpole_bitmap (NULL)
{
m_pattern.data[0] = 0x0f;
m_pattern.data[1] = 0x1e;
m_pattern.data[2] = 0x3c;
m_pattern.data[3] = 0x78;
m_pattern.data[4] = 0xf0;
m_pattern.data[5] = 0xe1;
m_pattern.data[6] = 0xc3;
m_pattern.data[7] = 0x87;
CreateBitmap();
};
Activity::~Activity()
{
// subviews are deleted by superclass
delete m_barberpole_bitmap;
}
void
Activity::Start()
{
m_is_running = true;
Window()->SetPulseRate(100000);
SetFlags(Flags() | B_PULSE_NEEDED);
SetViewColor(B_TRANSPARENT_COLOR);
Invalidate();
}
void
Activity::Pause()
{
Window()->SetPulseRate(500000);
SetFlags(Flags() & (~ B_PULSE_NEEDED));
Invalidate();
}
void
Activity::Stop()
{
m_is_running = false;
Window()->SetPulseRate(500000);
SetFlags(Flags() & (~ B_PULSE_NEEDED));
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
Invalidate();
}
bool
Activity::IsRunning()
{
return m_is_running;
}
void
Activity::Pulse()
{
uchar tmp = m_pattern.data[7];
for (int j = 7; j > 0; --j)
{
m_pattern.data[j] = m_pattern.data[j-1];
}
m_pattern.data[0] = tmp;
DrawIntoBitmap();
Invalidate();
}
void
Activity::Draw(BRect a_rect)
{
if (IsRunning())
{
// draw BBox outline
BBox::Draw(a_rect);
SetDrawingMode(B_OP_COPY);
DrawBitmap(m_barberpole_bitmap);
}
else
{
BBox::Draw(a_rect);
float string_width = StringWidth("Drop files to zip.");
float view_width = Bounds().Width();
MovePenTo ((view_width/2)-(string_width/2),12);
DrawString("Drop files to zip.");
}
}
void Activity::DrawIntoBitmap (void)
{
if (m_barberpole_bitmap->Lock())
{
BRect a_rect = m_barberpole_bitmap->Bounds();
m_barberpole_bitmap_view->SetDrawingMode(B_OP_COPY);
rgb_color color;
color.red = 0;
color.green = 0;
color.blue = 200;
color.alpha = 255;
m_barberpole_bitmap_view->SetHighColor(color);
// draw the pole
a_rect.InsetBy(2,2);
m_barberpole_bitmap_view->FillRect(a_rect, m_pattern);
// draw frame
// left
color.red = 150;
color.green = 150;
color.blue = 150;
m_barberpole_bitmap_view->SetHighColor(color);
BPoint point_a = m_barberpole_bitmap->Bounds().LeftTop();
BPoint point_b = m_barberpole_bitmap->Bounds().LeftBottom();
point_b.y -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
point_a.x += 1;
point_b.x += 1;
point_b.y -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
// top
m_barberpole_bitmap_view->SetDrawingMode(B_OP_OVER);
m_barberpole_bitmap_view->SetHighColor(color);
point_a = m_barberpole_bitmap->Bounds().LeftTop();
point_b = m_barberpole_bitmap->Bounds().RightTop();
point_b.x -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
point_a.y += 1;
point_b.y += 1;
point_b.x -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
// right
color.red = 255;
color.green = 255;
color.blue = 255;
m_barberpole_bitmap_view->SetHighColor(color);
point_a = m_barberpole_bitmap->Bounds().RightTop();
point_b = m_barberpole_bitmap->Bounds().RightBottom();
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
point_a.y += 1;
point_a.x -= 1;
point_b.x -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
// bottom
m_barberpole_bitmap_view->SetHighColor(color);
point_a = m_barberpole_bitmap->Bounds().LeftBottom();
point_b = m_barberpole_bitmap->Bounds().RightBottom();
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
point_a.x += 1;
point_a.y -= 1;
point_b.y -= 1;
m_barberpole_bitmap_view->StrokeLine(point_a, point_b);
// some blending
color.red = 150;
color.green = 150;
color.blue = 150;
m_barberpole_bitmap_view->SetHighColor(color);
m_barberpole_bitmap_view->SetDrawingMode(B_OP_SUBTRACT);
m_barberpole_bitmap_view->StrokeRect(a_rect);
a_rect.InsetBy(1,1);
LightenBitmapHighColor(& color);
m_barberpole_bitmap_view->StrokeRect(a_rect);
a_rect.InsetBy(1,1);
LightenBitmapHighColor(& color);
m_barberpole_bitmap_view->StrokeRect(a_rect);
a_rect.InsetBy(1,1);
LightenBitmapHighColor(& color);
m_barberpole_bitmap_view->StrokeRect(a_rect);
a_rect.InsetBy(1,1);
LightenBitmapHighColor(& color);
m_barberpole_bitmap_view->StrokeRect(a_rect);
m_barberpole_bitmap_view->Flush();
}
m_barberpole_bitmap->Unlock();
}
void Activity::LightenBitmapHighColor (rgb_color * a_color)
{
a_color->red -= 30;
a_color->green -= 30;
a_color->blue -= 30;
m_barberpole_bitmap_view->SetHighColor(* a_color);
}
void Activity::CreateBitmap (void)
{
BRect barberpole_rect = Bounds();
m_barberpole_bitmap = new BBitmap(barberpole_rect, B_CMAP8, true);
m_barberpole_bitmap_view = new BView(Bounds(), "buffer", B_FOLLOW_NONE, 0);
m_barberpole_bitmap->AddChild(m_barberpole_bitmap_view);
}
void Activity::FrameMoved (BPoint a_point)
{
delete m_barberpole_bitmap;
CreateBitmap();
Invalidate();
}
void Activity::FrameResized (float a_width, float a_height)
{
delete m_barberpole_bitmap;
CreateBitmap();
Invalidate();
}

View File

@ -0,0 +1,42 @@
#ifndef _ACTIVITY_H_
#define _ACTIVITY_H_
#include <stdlib.h>
#include <Window.h>
#include <View.h>
#include <Box.h>
#include <Bitmap.h>
class Activity : public BBox
{
public:
Activity (BRect a_rect, const char * a_name, uint32 a_resizing_mode,
uint32 a_flags);
~Activity ();
void Start ();
void Pause ();
void Stop ();
bool IsRunning ();
virtual void Pulse ();
virtual void Draw (BRect a_draw);
virtual void FrameMoved (BPoint a_point);
virtual void FrameResized (float a_width, float a_height);
protected:
void CreateBitmap (void);
void LightenBitmapHighColor (rgb_color * a_color);
void DrawIntoBitmap (void);
bool m_is_running;
pattern m_pattern;
BBitmap * m_barberpole_bitmap;
BView * m_barberpole_bitmap_view;
private:
};
#endif

View File

@ -0,0 +1,47 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <ZipOMaticMisc.h>
#include <Debug.h>
status_t
find_and_create_directory (directory_which a_which, BVolume * a_volume, const char * a_relative_path, BPath * a_full_path)
{
status_t status = B_OK;
BPath path;
mode_t mask = 0;
status = find_directory (a_which, & path, true, a_volume); // create = true
if (status != B_OK)
return status;
if (a_relative_path != NULL)
{
path.Append(a_relative_path);
mask = umask (0);
umask (mask);
status = create_directory (path.Path(), mask);
if (status != B_OK)
return status;
}
if (a_full_path != NULL)
{
status = a_full_path->SetTo(path.Path());
if (status != B_OK)
return status;
}
return B_OK;
}
void
error_message (const char * a_text, int32 a_status)
{
PRINT(("%s: %s\n", a_text, strerror(a_status)));
}

View File

@ -0,0 +1,24 @@
#ifndef __ZIPOMATIC_MISC__
#define __ZIPOMATIC_MISC__
#include <stdlib.h>
#include <stdio.h>
#include <String.h>
#include <SupportDefs.h>
#include <Volume.h>
#include <Path.h>
#include <Directory.h>
#include <FindDirectory.h>
#define ZIPOMATIC_APP_SIG "application/x-vnd.obos.zip-o-matic"
#define ZIPOMATIC_APP_NAME "ZipOMatic"
#define ZIPPO_WINDOW_QUIT 'winq'
status_t find_and_create_directory (directory_which a_which, BVolume * a_volume = NULL, const char * a_relative_path = NULL, BPath * a_full_path = NULL);
void error_message (const char * a_text, int32 a_status);
#endif // __ZIPOMATIC_MISC__

View File

@ -0,0 +1,140 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
//
// TODO: proper locking <<---------
//
#include <Debug.h>
#include <VolumeRoster.h>
#include <FindDirectory.h>
#include <Directory.h>
#include <Path.h>
#include <File.h>
#include <ZipOMaticMisc.h>
#include <ZipOMaticSettings.h>
ZippoSettings::ZippoSettings()
: BMessage (),
m_volume (),
m_base_dir (B_USER_SETTINGS_DIRECTORY),
m_relative_path (),
m_settings_filename ()
{
PRINT(("ZippoSettings()\n"));
}
ZippoSettings::ZippoSettings(BMessage a_message)
: BMessage (a_message),
m_volume (),
m_base_dir (B_USER_SETTINGS_DIRECTORY),
m_relative_path (),
m_settings_filename ()
{
PRINT(("ZippoSettings(a_message)\n"));
}
ZippoSettings::~ZippoSettings()
{
m_volume.Unset();
}
status_t
ZippoSettings::SetTo (const char * a_settings_filename,
BVolume * a_volume,
directory_which a_base_dir,
const char * a_relative_path)
{
status_t status = B_OK;
// copy to members
m_base_dir = a_base_dir;
m_relative_path = a_relative_path;
m_settings_filename = a_settings_filename;
// sanity check
if (a_volume == NULL)
{
BVolumeRoster volume_roster;
volume_roster.GetBootVolume(& m_volume);
}
else
m_volume = *(a_volume);
status = m_volume.InitCheck();
if (status != B_OK)
return status;
// InitCheck
return InitCheck();
}
status_t
ZippoSettings::InitCheck (void)
{
BFile settings_file;
return GetSettingsFile (& settings_file, B_READ_ONLY | B_CREATE_FILE);
}
status_t
ZippoSettings::GetSettingsFile (BFile * a_settings_file, uint32 a_openmode)
{
status_t status = B_OK;
BPath settings_path;
status = find_and_create_directory(m_base_dir, & m_volume, m_relative_path.String(), & settings_path);
if (status != B_OK)
return status;
status = settings_path.Append (m_settings_filename.String());
if (status != B_OK)
return status;
status = a_settings_file->SetTo (settings_path.Path(), a_openmode);
if (status != B_OK)
return status;
return B_OK;
}
status_t
ZippoSettings::ReadSettings (void)
{
PRINT(("ZippoSettings::ReadSettings()\n"));
status_t status = B_OK;
BFile settings_file;
status = GetSettingsFile (& settings_file, B_READ_ONLY);
if (status != B_OK)
return status;
status = Unflatten(& settings_file);
if (status != B_OK)
return status;
return B_OK;
}
status_t
ZippoSettings::WriteSettings (void)
{
PRINT(("ZippoSettings::WriteSettings()\n"));
status_t status = B_OK;
BFile settings_file;
status = GetSettingsFile (& settings_file, B_WRITE_ONLY | B_ERASE_FILE);
if (status != B_OK)
return status;
status = Flatten(& settings_file);
if (status != B_OK)
return status;
return B_OK;
}

View File

@ -0,0 +1,36 @@
#ifndef __ZIPPO_SETTINGS_H__
#define __ZIPPO_SETTINGS_H__
#include <Message.h>
#include <Volume.h>
#include <String.h>
class ZippoSettings : public BMessage
{
public:
ZippoSettings ();
ZippoSettings (BMessage a_message);
~ZippoSettings ();
status_t SetTo (const char * a_settings_filename,
BVolume * a_volume = NULL,
directory_which a_base_dir = B_USER_SETTINGS_DIRECTORY,
const char * a_relative_path = NULL);
status_t InitCheck (void);
status_t ReadSettings ();
status_t WriteSettings ();
private:
status_t GetSettingsFile (BFile * a_settings_file, uint32 a_openmode);
BVolume m_volume;
directory_which m_base_dir;
BString m_relative_path;
BString m_settings_filename;
};
#endif // __ZIPPO_SETTINGS_H__

View File

@ -0,0 +1,87 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <ZipOMaticActivity.h>
#include <ZipOMaticView.h>
ZippoView::ZippoView (BRect a_rect)
: BBox (a_rect, "zipomatic_view", B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
B_PLAIN_BORDER),
m_stop_button (NULL)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// "Stop" button
BRect button_rect (a_rect.right-82, a_rect.bottom-32, a_rect.right-12, a_rect.bottom-12);
m_stop_button = new BButton(button_rect,"stop_button","Stop", new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT);
m_stop_button->SetEnabled(false);
AddChild(m_stop_button);
// activity view
BRect activity_rect (a_rect.left+14, a_rect.top+15, a_rect.right-15, a_rect.top+31);
m_activity_view = new Activity (activity_rect, "activity_view", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS);
AddChild(m_activity_view);
// text views
BRect archive_rect (a_rect.left+14, a_rect.top+30, a_rect.right-15, a_rect.top+47);
m_archive_name_view = new BStringView (archive_rect, "archive_text", " ", B_FOLLOW_LEFT_RIGHT);
AddChild (m_archive_name_view);
BRect ouput_rect (a_rect.left+14, a_rect.top+47, a_rect.right-15, a_rect.top+66);
m_zip_output_view = new BStringView (ouput_rect, "output_text", " ", B_FOLLOW_LEFT_RIGHT);
AddChild (m_zip_output_view);
}
void ZippoView::Draw (BRect a_update_rect)
{
BBox::Draw(a_update_rect);
// fBox->DrawBitmap(fIconBitmap,BPoint(178,26));
const rgb_color grey_accent = {128,128,128,255};
const rgb_color darker_grey = {108,108,108,255};
const rgb_color plain_white = {255,255,255,255};
const rgb_color deep_black = {255,255,255,255};
// "preflet" bottom, right grey accent lines
SetHighColor(grey_accent);
StrokeLine (BPoint(Bounds().right, Bounds().top),
BPoint(Bounds().right, Bounds().bottom));
StrokeLine (BPoint(Bounds().left, Bounds().bottom),
BPoint(Bounds().right, Bounds().bottom));
// divider
SetHighColor(darker_grey);
StrokeLine (BPoint(Bounds().left+15, Bounds().top+71),
BPoint(Bounds().right-16, Bounds().top+71));
SetHighColor(plain_white);
StrokeLine (BPoint(Bounds().left+15, Bounds().top+72),
BPoint(Bounds().right-16, Bounds().top+72));
// text
SetHighColor(deep_black);
}
void ZippoView::AllAttached (void)
{
}
void ZippoView::FrameMoved (BPoint a_point)
{
Invalidate();
}
void ZippoView::FrameResized (float a_width, float a_height)
{
Invalidate();
}

View File

@ -0,0 +1,31 @@
#ifndef __ZIPPO_VIEW_H__
#define __ZIPPO_VIEW_H__
#include <Box.h>
#include <Button.h>
#include <StringView.h>
class Activity;
class ZippoView : public BBox
{
public:
ZippoView (BRect frame);
virtual void Draw (BRect frame);
virtual void AllAttached (void);
virtual void FrameMoved (BPoint a_point);
virtual void FrameResized (float a_width, float a_height);
BButton * m_stop_button;
Activity * m_activity_view;
BStringView * m_archive_name_view;
BStringView * m_zip_output_view;
private:
};
#endif // __ZIPPO_VIEW_H__

View File

@ -0,0 +1,328 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
#include <Debug.h>
#include <stdio.h>
#include <stdlib.h>
#include <Application.h>
#include <Roster.h>
#include <InterfaceKit.h>
#include <String.h>
#include <FindDirectory.h>
#include <Directory.h>
#include <Path.h>
#include <File.h>
#include <ZipOMatic.h>
#include <ZipOMaticActivity.h>
#include <ZipOMaticMisc.h>
#include <ZipOMaticView.h>
#include <ZipOMaticWindow.h>
#include <ZipOMaticZipper.h>
ZippoWindow::ZippoWindow(BMessage * a_message)
: BWindow(BRect(200,200,430,310), "Zip-O-Matic", B_TITLED_WINDOW, B_NOT_V_RESIZABLE), // | B_NOT_ZOOMABLE),
m_zippo_settings (),
m_zipper_thread (NULL),
m_got_refs_at_window_startup (false),
m_zipping_was_stopped (false),
m_alert_invoker_message (new BMessage ('alrt')),
m_alert_window_invoker (new BInvoker (m_alert_invoker_message, NULL, this))
{
PRINT(("ZippoWindow()\n"));
// Settings
status_t status = B_OK;
status = m_zippo_settings.SetTo("ZipOMatic.msg");
if (status != B_OK)
error_message("ZippoWindow() - m_zippo_settings.SetTo()", status);
status = m_zippo_settings.InitCheck();
if (status != B_OK)
error_message("ZippoWindow() - m_zippo_settings.InitCheck()", status);
// Interface
zippoview = new ZippoView(Bounds());
AddChild (zippoview);
SetSizeLimits(Bounds().Width(), 15000, Bounds().Height(), Bounds().Height());
// Settings, (on-screen location of window)
ReadSettings();
// Start zipper thread
if (a_message != NULL)
{
m_got_refs_at_window_startup = true;
StartZipping (a_message);
}
}
ZippoWindow::~ZippoWindow()
{
PRINT(("ZippoWindow::~ZippoWindow()\n"));
//delete m_alert_invoker_message;
delete m_alert_window_invoker;
// anything left to clean up?
}
void
ZippoWindow::MessageReceived (BMessage * a_message)
{
switch(a_message->what)
{
case B_REFS_RECEIVED:
StartZipping (a_message);
break;
case B_SIMPLE_DATA:
if (IsZipping())
{
a_message->what = B_REFS_RECEIVED;
be_app_messenger.SendMessage(a_message);
}
else
StartZipping (a_message);
break;
case 'exit': // thread has finished (finished, quit, killed, we don't know)
// reset window state
{
m_zipper_thread = NULL;
zippoview->m_activity_view->Stop();
zippoview->m_archive_name_view->SetText(" ");
if (m_zipping_was_stopped)
zippoview->m_zip_output_view->SetText("Stopped");
else
zippoview->m_zip_output_view->SetText("Archive created OK");
CloseWindowOrKeepOpen();
break;
}
case 'exrr': // thread has finished
// reset window state
m_zipper_thread = NULL;
zippoview->m_activity_view->Stop();
zippoview->m_archive_name_view->SetText("");
zippoview->m_zip_output_view->SetText("Error creating archive");
//CloseWindowOrKeepOpen();
break;
case 'strt':
{
BString archive_filename;
if (a_message->FindString("archive_filename", & archive_filename) == B_OK)
zippoview->m_archive_name_view->SetText(archive_filename.String());
break;
}
case 'outp':
{
BString zip_output;
if (a_message->FindString("zip_output", & zip_output) == B_OK)
zippoview->m_zip_output_view->SetText(zip_output.String());
break;
}
case 'alrt':
{
int32 which_button = -1;
if (a_message->FindInt32("which", & which_button) == B_OK)
if (which_button == 0)
StopZipping();
else
{
if (m_zipper_thread != NULL)
m_zipper_thread->ResumeExternalZip();
zippoview->m_activity_view->Start();
}
break;
}
default: BWindow::MessageReceived(a_message); break;
}
}
bool
ZippoWindow::QuitRequested (void)
{
PRINT(("ZippoWindow::QuitRequested()\n"));
if (m_zipper_thread == NULL)
{
WriteSettings();
be_app_messenger.SendMessage(ZIPPO_WINDOW_QUIT);
return true;
}
else
{
if (m_zipper_thread != NULL)
m_zipper_thread->SuspendExternalZip();
zippoview->m_activity_view->Pause();
BAlert * quit_requester = new BAlert ("Stop or Continue", "Are you sure you want to "
"stop creating this archive?", "Stop", "Continue",
NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
quit_requester->Go(m_alert_window_invoker);
return false;
}
}
status_t
ZippoWindow::ReadSettings (void)
{
status_t status = B_OK;
status = m_zippo_settings.InitCheck();
if (status != B_OK)
error_message("m_zippo_settings.InitCheck()", status);
status = m_zippo_settings.ReadSettings();
if (status != B_OK)
error_message("m_zippo_settings.ReadSettings()", status);
BRect window_rect;
status = m_zippo_settings.FindRect("window_rect", & window_rect);
if (status != B_OK)
{
error_message("m_settings_message->FindRect(window_rect)", status);
return status;
}
ResizeTo (window_rect.Width(), window_rect.Height());
MoveTo (window_rect.LeftTop());
return B_OK;
}
status_t
ZippoWindow::WriteSettings (void)
{
status_t status = B_OK;
status = m_zippo_settings.InitCheck();
if (status != B_OK)
error_message("m_zippo_settings.InitCheck()", status);
status = m_zippo_settings.MakeEmpty();
if (status != B_OK)
error_message("m_zippo_settings.MakeEmpty()", status);
status = m_zippo_settings.AddRect("window_rect", Frame());
if (status != B_OK)
{
error_message("m_settings_message->AddRect(window_rect)", status);
return status;
}
status = m_zippo_settings.WriteSettings();
if (status != B_OK)
{
error_message("m_zippo_settings.WriteSettings()", status);
return status;
}
return B_OK;
}
void
ZippoWindow::StartZipping (BMessage * a_message)
{
PRINT(("ZippoWindow::StartZipping()\n"));
zippoview->m_stop_button->SetEnabled(true);
zippoview->m_activity_view->Start();
m_zipper_thread = new ZipperThread (a_message, this);
m_zipper_thread->Start();
m_zipping_was_stopped = false;
}
void
ZippoWindow::StopZipping (void)
{
PRINT(("ZippoWindow::StopZipping()\n"));
m_zipping_was_stopped = true;
zippoview->m_stop_button->SetEnabled(false);
zippoview->m_activity_view->Stop();
m_zipper_thread->InterruptExternalZip();
m_zipper_thread->Quit();
status_t status = B_OK;
m_zipper_thread->WaitForThread (& status);
m_zipper_thread = NULL;
zippoview->m_archive_name_view->SetText(" ");
zippoview->m_zip_output_view->SetText("Stopped");
CloseWindowOrKeepOpen();
}
bool
ZippoWindow::IsZipping (void)
{
if (m_zipper_thread == NULL)
return false;
else
return true;
}
void
ZippoWindow::CloseWindowOrKeepOpen (void)
{
if (m_got_refs_at_window_startup)
PostMessage(B_QUIT_REQUESTED);
}
void
ZippoWindow::Zoom (BPoint origin, float width, float height)
{
/*
float archive_name_view_preferred_width;
float zip_output_view_preferred_width;
float throw_away_height;
zippoview->GetPreferredSize(& archive_name_view_preferred_width, & throw_away_height);
zippoview->GetPreferredSize(& zip_output_view_preferred_width, & throw_away_height);
*/
// BStringView::GetPreferredSize appears to be broken,
// so we have to use BView::StringWidth() instead
if (IsZipping())
{
float archive_name_view_preferred_width = zippoview->StringWidth(zippoview->m_archive_name_view->Text());
float zip_output_view_preferred_width = zippoview->StringWidth(zippoview->m_zip_output_view->Text());
float the_wide_string;
if (zip_output_view_preferred_width > archive_name_view_preferred_width)
the_wide_string = zip_output_view_preferred_width;
else
the_wide_string = archive_name_view_preferred_width;
ResizeTo(the_wide_string, Bounds().Height());
}
else
{
ResizeTo(230,110);
}
}

View File

@ -0,0 +1,46 @@
#ifndef __ZIPPO_WINDOW_H__
#define __ZIPPO_WINDOW_H__
#include <Window.h>
#include <MenuBar.h>
#include <Bitmap.h>
#include <Menu.h>
#include <MenuItem.h>
#include <ZipOMaticSettings.h>
class ZippoView;
class ZipperThread;
class ZippoWindow : public BWindow
{
public:
ZippoWindow (BMessage * a_message = NULL);
~ZippoWindow (void);
virtual void MessageReceived (BMessage * a_message);
virtual bool QuitRequested (void);
virtual void Zoom (BPoint origin, float width, float height);
bool IsZipping (void);
private:
status_t ReadSettings (void);
status_t WriteSettings (void);
void StartZipping (BMessage * a_message);
void StopZipping (void);
void CloseWindowOrKeepOpen (void);
ZippoView * zippoview;
ZippoSettings m_zippo_settings;
ZipperThread * m_zipper_thread;
bool m_got_refs_at_window_startup;
bool m_zipping_was_stopped;
BMessage * m_alert_invoker_message;
BInvoker * m_alert_window_invoker;
};
#endif // __ZIPPO_WINDOW_H__

View File

@ -0,0 +1,388 @@
// license: public domain
// authors: jonas.sundstrom@kirilla.com
//
// exception: ZipperThread::PipeCommand()
// written by Peter Folk, published in the BeDevTalk mailinglist FAQ
// License unknown, most likely public domain
#include <Debug.h>
#include <Path.h>
#include <ZipOMaticZipper.h>
#include <ZipOMaticWindow.h>
#include <ZipOMaticMisc.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
const char * ZipperThreadName = "ZipperThread";
ZipperThread::ZipperThread (BMessage * a_refs_message, BWindow * a_window)
: GenericThread(ZipperThreadName, B_NORMAL_PRIORITY, a_refs_message),
m_window (a_window),
m_window_messenger (new BMessenger(NULL, a_window)),
m_zip_process_thread_id (-1),
m_std_in (-1),
m_std_out (-1),
m_std_err (-1),
m_zip_output (NULL),
m_zip_output_string (),
m_zip_output_buffer (new char [4096])
{
PRINT(("ZipperThread()\n"));
m_thread_data_store = new BMessage (* a_refs_message); // leak?
// prevents bug with B_SIMPLE_DATA
// (drag&drop messages)
}
ZipperThread::~ZipperThread()
{
delete m_window_messenger;
delete [] m_zip_output_buffer;
}
status_t
ZipperThread::ThreadStartup (void)
{
PRINT(("ZipperThread::ThreadStartup()\n"));
// init
status_t status = B_OK;
entry_ref ref;
entry_ref last_ref;
bool same_folder = true;
BString zip_archive_filename = "Archive.zip";
// do all refs have the same parent dir?
type_code ref_type = B_REF_TYPE;
int32 ref_count = 0;
status = m_thread_data_store->GetInfo("refs", & ref_type, & ref_count);
if (status != B_OK)
return status;
for (int index = 0; index < ref_count ; index++)
{
m_thread_data_store->FindRef("refs", index, & ref);
if (index > 0)
{
BEntry entry (& ref);
if (entry.IsSymLink())
{
entry.SetTo(& ref, true);
entry_ref target;
entry.GetRef(& target);
if (last_ref.directory != target.directory)
{
same_folder = false;
break;
}
}
else
if (last_ref.directory != ref.directory)
{
same_folder = false;
break;
}
}
last_ref = ref;
}
// change active dir
if (same_folder)
{
BEntry entry (& last_ref);
BPath path;
entry.GetParent(& entry);
entry.GetPath(& path);
chdir(path.Path());
}
else
{
BPath path;
if (find_directory(B_DESKTOP_DIRECTORY, & path) == B_OK)
chdir (path.Path());
}
// archive filename
if (ref_count == 1)
{
zip_archive_filename = last_ref.name;
zip_archive_filename += ".zip";
}
int32 argc = ref_count + 3;
const char ** argv = new const char * [argc + 1];
argv[0] = strdup("/bin/zip");
argv[1] = strdup("-ry");
argv[2] = strdup(zip_archive_filename.String());
// files to zip
for (int ref_index = 0; ref_index < ref_count ; ref_index++)
{
m_thread_data_store->FindRef("refs", ref_index, & ref);
if (same_folder)
{
argv[3 + ref_index] = strdup(ref.name); // just the file name
}
else
{
BPath path (& ref);
BString file = path.Path();
argv[3 + ref_index] = strdup(path.Path()); // full path
}
}
argv[argc] = NULL;
m_zip_process_thread_id = PipeCommand (argc, argv, m_std_in, m_std_out, m_std_err);
delete [] argv;
if (m_zip_process_thread_id < 0)
return (m_zip_process_thread_id);
resume_thread (m_zip_process_thread_id);
m_zip_output = fdopen (m_std_out, "r");
zip_archive_filename.Prepend("Creating archive: ");
SendMessageToWindow ('strt', "archive_filename", zip_archive_filename.String());
SendMessageToWindow ('outp', "zip_output", "Preparing to archive");
PRINT(("\n"));
return B_OK;
}
status_t
ZipperThread::ExecuteUnit (void)
{
//PRINT(("ZipperThread::ExecuteUnit()\n"));
// read output from /bin/zip
// send it to window
char * output_string;
output_string = fgets(m_zip_output_buffer , 4096-1, m_zip_output);
if (output_string == NULL)
{
return EOF;
}
else
{
char * new_line_ptr = strrchr(output_string, '\n');
if (new_line_ptr != NULL)
*new_line_ptr = '\0';
if (! strncmp(" a", m_zip_output_buffer, 3))
{
m_zip_output_buffer[2] = 'A';
SendMessageToWindow ('outp', "zip_output", output_string + 2);
}
else if (! strncmp("up", m_zip_output_buffer, 2))
{
m_zip_output_buffer[0] = 'U';
SendMessageToWindow ('outp', "zip_output", output_string);
}
else
{
SendMessageToWindow ('outp', "zip_output", output_string);
}
}
return B_OK;
}
status_t
ZipperThread::ThreadShutdown (void)
{
PRINT(("ZipperThread::ThreadShutdown()\n"));
close(m_std_in);
close(m_std_out);
close(m_std_err);
return B_OK;
}
void
ZipperThread::ThreadStartupFailed (status_t a_status)
{
error_message("ZipperThread::ThreadStartupFailed() \n", a_status);
Quit();
}
void
ZipperThread::ExecuteUnitFailed (status_t a_status)
{
error_message("ZipperThread::ExecuteUnitFailed() \n", a_status);
if (a_status == EOF)
{
// thread has finished, been quit or killed, we don't know
SendMessageToWindow ('exit');
}
else
{
// explicit error - communicate error to Window
SendMessageToWindow ('exrr');
}
Quit();
}
void
ZipperThread::ThreadShutdownFailed (status_t a_status)
{
error_message("ZipperThread::ThreadShutdownFailed() \n", a_status);
}
void
ZipperThread::MakeShellSafe (BString * a_string)
{
a_string->CharacterEscape("\"$`", '\\');
a_string->Prepend("\"");
a_string->Append("\"");
}
status_t
ZipperThread::ProcessRefs (BMessage * msg)
{
return B_OK;
}
thread_id
ZipperThread::PipeCommand (int argc, const char **argv, int & in, int & out, int & err, const char **envp)
{
// This function 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 old_in = dup(0);
int old_out = dup(1);
int old_err = dup(2);
int filedes[2];
/* Create new pipe FDs as stdin, stdout, stderr */
pipe(filedes); dup2(filedes[0],0); close(filedes[0]);
in=filedes[1]; // Write to in, appears on cmd's stdin
pipe(filedes); dup2(filedes[1],1); close(filedes[1]);
out=filedes[0]; // Read from out, taken from cmd's stdout
pipe(filedes); dup2(filedes[1],2); close(filedes[1]);
err=filedes[0]; // Read from err, taken from cmd's stderr
// "load" command.
thread_id ret = load_image(argc, argv, envp);
// thread ret is now suspended.
PRINT(("load_image() thread_id: %ld\n", ret));
// Restore old FDs
close(0); dup(old_in); close(old_in);
close(1); dup(old_out); close(old_out);
close(2); dup(old_err); close(old_err);
/* Theoretically I should do loads of error checking, but
the calls aren't very likely to fail, and that would
muddy up the example quite a bit. YMMV. */
return ret;
}
void
ZipperThread::SendMessageToWindow (uint32 a_msg_what, const char * a_string_name, const char * a_string_value)
{
BMessage msg (a_msg_what);
if (! (a_string_name == NULL || a_string_value == NULL))
msg.AddString(a_string_name, a_string_value);
m_window_messenger->SendMessage(& msg);
}
status_t
ZipperThread::SuspendExternalZip (void)
{
PRINT(("ZipperThread::SuspendExternalZip()\n"));
status_t status = B_OK;
thread_info zip_thread_info;
status = get_thread_info (m_zip_process_thread_id, & zip_thread_info);
BString thread_name = zip_thread_info.name;
if (status == B_OK && thread_name == "zip")
return suspend_thread (m_zip_process_thread_id);
else
return status;
}
status_t
ZipperThread::ResumeExternalZip (void)
{
PRINT(("ZipperThread::ResumeExternalZip()\n"));
status_t status = B_OK;
thread_info zip_thread_info;
status = get_thread_info (m_zip_process_thread_id, & zip_thread_info);
BString thread_name = zip_thread_info.name;
if (status == B_OK && thread_name == "zip")
return resume_thread (m_zip_process_thread_id);
else
return status;
}
status_t
ZipperThread::InterruptExternalZip (void)
{
PRINT(("ZipperThread::InterruptExternalZip()\n"));
status_t status = B_OK;
thread_info zip_thread_info;
status = get_thread_info (m_zip_process_thread_id, & zip_thread_info);
BString thread_name = zip_thread_info.name;
if (status == B_OK && thread_name == "zip")
{
status = B_OK;
status = send_signal (m_zip_process_thread_id, SIGINT);
WaitOnExternalZip();
return status;
}
else
return status;
}
status_t
ZipperThread::WaitOnExternalZip (void)
{
PRINT(("ZipperThread::WaitOnExternalZip()\n"));
status_t status = B_OK;
thread_info zip_thread_info;
status = get_thread_info (m_zip_process_thread_id, & zip_thread_info);
BString thread_name = zip_thread_info.name;
if (status == B_OK && thread_name == "zip")
return wait_for_thread (m_zip_process_thread_id, & status);
else
return status;
}

View File

@ -0,0 +1,61 @@
#ifndef __ZIPOMATIC_ZIPPER_H__
#define __ZIPOMATIC_ZIPPER_H__
#include <Message.h>
#include <Volume.h>
#include <String.h>
#include <Window.h>
#include <OS.h>
#include <FindDirectory.h>
#include <GenericThread.h>
#include <stdlib.h>
extern const char * ZipperThreadName;
class ZipperThread : public GenericThread
{
public:
ZipperThread (BMessage * a_refs_message, BWindow * a_window);
~ZipperThread ();
status_t SuspendExternalZip (void);
status_t ResumeExternalZip (void);
status_t InterruptExternalZip (void);
status_t WaitOnExternalZip (void);
private:
virtual status_t ThreadStartup (void);
virtual status_t ExecuteUnit (void);
virtual status_t ThreadShutdown (void);
virtual void ThreadStartupFailed (status_t a_status);
virtual void ExecuteUnitFailed (status_t a_status);
virtual void ThreadShutdownFailed (status_t a_status);
status_t ProcessRefs (BMessage * msg);
void MakeShellSafe (BString * a_string);
thread_id PipeCommand (int argc, const char **argv,
int & in, int & out, int & err,
const char **envp = (const char **) environ);
void SendMessageToWindow (uint32 a_msg_what,
const char * a_string_name = NULL,
const char * a_string_value = NULL);
BWindow * m_window;
BMessenger * m_window_messenger;
int32 m_zip_process_thread_id;
int m_std_in;
int m_std_out;
int m_std_err;
FILE * m_zip_output;
BString m_zip_output_string;
char * m_zip_output_buffer;
};
#endif // __ZIPOMATIC_ZIPPER_H__