* Implemented the Terminal-ID search using a BClipboard and the new atomicity

feature of BClipboard::Commit().
* The file based version is now only used when the Terminal is built for BeOS.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20941 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-04-30 21:22:26 +00:00
parent f96bec013d
commit d1c710a7d8
2 changed files with 128 additions and 25 deletions

View File

@ -17,6 +17,7 @@
#include "TermConst.h"
#include <Alert.h>
#include <Clipboard.h>
#include <NodeInfo.h>
#include <Path.h>
#include <Roster.h>
@ -428,6 +429,75 @@ TermApp::_IsMinimized(team_id id)
}
/*!
Checks if all teams that have an ID-to-team mapping in the message
are still running.
The IDs for teams that are gone will be made available again, and
their mapping is removed from the message.
*/
void
TermApp::_SanitizeIDs(BMessage* data, uint8* windows, ssize_t length)
{
BList teams;
be_roster->GetAppList(TERM_SIGNATURE, &teams);
for (int32 i = 0; i < length; i++) {
if (!windows[i])
continue;
BString id("id-");
id << i;
team_id team;
if (data->FindInt32(id.String(), &team) != B_OK)
continue;
if (!teams.HasItem((void*)team)) {
windows[i] = false;
data->RemoveName(id.String());
}
}
}
/*!
Removes the current fWindowNumber (ID) from the supplied array, or
finds a free ID in it, and sets fWindowNumber accordingly.
*/
bool
TermApp::_UpdateIDs(bool set, uint8* windows, ssize_t maxLength,
ssize_t* _length)
{
ssize_t length = *_length;
if (set) {
int32 i;
for (i = 0; i < length; i++) {
if (!windows[i]) {
windows[i] = true;
fWindowNumber = i + 1;
break;
}
}
if (i == length) {
if (length >= maxLength)
return false;
windows[length] = true;
length++;
fWindowNumber = length;
}
} else {
// update information and write it back
windows[fWindowNumber - 1] = false;
}
*_length = length;
return true;
}
void
TermApp::_UpdateRegistration(bool set)
{
@ -436,6 +506,56 @@ TermApp::_UpdateRegistration(bool set)
else if (fWindowNumber < 0)
return;
#ifdef __HAIKU__
// use BClipboard - it supports atomic access in Haiku
BClipboard clipboard(TERM_SIGNATURE);
while (true) {
if (!clipboard.Lock())
return;
BMessage* data = clipboard.Data();
const uint8* windowsData;
uint8 windows[512];
ssize_t length;
if (data->FindData("ids", B_RAW_TYPE,
(const void**)&windowsData, &length) != B_OK)
length = 0;
if (length > (ssize_t)sizeof(windows))
length = sizeof(windows);
if (length > 0)
memcpy(windows, windowsData, length);
_SanitizeIDs(data, windows, length);
status_t status = B_OK;
if (_UpdateIDs(set, windows, sizeof(windows), &length)) {
// add/remove our ID-to-team mapping
BString id("id-");
id << fWindowNumber;
if (set)
data->AddInt32(id.String(), Team());
else
data->RemoveName(id.String());
data->RemoveName("ids");
//if (data->ReplaceData("ids", B_RAW_TYPE, windows, length) != B_OK)
data->AddData("ids", B_RAW_TYPE, windows, length);
status = clipboard.Commit(true);
}
clipboard.Unlock();
if (status == B_OK)
break;
}
#else // !__HAIKU__
// use a file to store the IDs - unfortunately, locking
// doesn't work on BeOS either here
int fd = open("/tmp/terminal_ids", O_RDWR | O_CREAT);
if (fd < 0)
return;
@ -447,41 +567,21 @@ TermApp::_UpdateRegistration(bool set)
lock.l_len = -1;
fcntl(fd, F_SETLKW, &lock);
uint8 windows[256];
uint8 windows[512];
ssize_t length = read_pos(fd, 0, windows, sizeof(windows));
if (length < 0) {
close(fd);
return;
}
if (length > (ssize_t)sizeof(windows))
length = sizeof(windows);
if (set) {
int32 i;
for (i = 0; i < length; i++) {
if (!windows[i]) {
windows[i] = true;
fWindowNumber = i + 1;
break;
}
}
if (i == length) {
if (length >= (ssize_t)sizeof(windows)) {
close(fd);
return;
}
if (_UpdateIDs(set, windows, sizeof(windows), &length))
write_pos(fd, 0, windows, length);
windows[length] = true;
length++;
fWindowNumber = length;
}
} else {
// update information and write it back
windows[fWindowNumber - 1] = false;
}
write_pos(fd, 0, windows, length);
close(fd);
#endif // !__HAIKU__
}

View File

@ -62,6 +62,9 @@ class TermApp : public BApplication {
void _SwitchTerm();
void _ActivateTermWindow(team_id id);
bool _IsMinimized(team_id id);
void _SanitizeIDs(BMessage* data, uint8* windows, ssize_t length);
bool _UpdateIDs(bool set, uint8* windows, ssize_t maxLength,
ssize_t* _length);
void _UpdateRegistration(bool set);
void _UnregisterTerminal();
void _RegisterTerminal();