Skip to content
Commits on Source (2)
# for variables passed from parent makefile see ../SOURCE_TOOLS/parent_make.txt
.SUFFIXES: .o .c .cxx .depend
OBJECTS = servercntrl.o
$(MAIN): $(OBJECTS)
$(LINK_STATIC_LIB) $(@) $(OBJECTS)
.c.o:
$(A_CC) $(cflags) -c $< $(CC_INCLUDES) $(POST_COMPILE)
.cxx.o:
$(A_CXX) $(cflags) $(cxxflags) -c $< $(CXX_INCLUDES) $(POST_COMPILE)
proto:
../AISC_MKPTPS/aisc_mkpt -P -w servercntrl.h $(OBJECTS:.o=.cxx) >servercntrl.h.tmp
../SOURCE_TOOLS/mv_if_diff servercntrl.h.tmp servercntrl.h
clean:
rm -f $(OBJECTS) *.a
DEPENDS = $(OBJECTS:.o=.depend)
depends: $(DEPENDS)
@cat $(DEPENDS) | grep -v '^#' >>Makefile
@rm $(DEPENDS)
$(DEPENDS): depend.init
depend.init:
$(MAKEDEPEND) $(MAKEDEPENDFLAGS) 2>/dev/null # remove dependencies
.c.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
.cxx.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
# DO NOT DELETE THIS LINE -- make depend depends on it.
# Do not add dependencies manually - use 'make depend' in $ARBHOME
# For formatting issues see SOURCE_TOOLS/fix_depends.pl (from main)
servercntrl.o: servercntrl.h
servercntrl.o: $(ARBHOME)/INCLUDE/ad_prot.h
servercntrl.o: $(ARBHOME)/INCLUDE/aisc_global.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_assert.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_core.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_error.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_file.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_msg.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_sleep.h
servercntrl.o: $(ARBHOME)/INCLUDE/arb_string.h
servercntrl.o: $(ARBHOME)/INCLUDE/arbdb.h
servercntrl.o: $(ARBHOME)/INCLUDE/arbdb_base.h
servercntrl.o: $(ARBHOME)/INCLUDE/arbtools.h
servercntrl.o: $(ARBHOME)/INCLUDE/attributes.h
servercntrl.o: $(ARBHOME)/INCLUDE/bytestring.h
servercntrl.o: $(ARBHOME)/INCLUDE/client.h
servercntrl.o: $(ARBHOME)/INCLUDE/client_privat.h
servercntrl.o: $(ARBHOME)/INCLUDE/client_types.h
servercntrl.o: $(ARBHOME)/INCLUDE/cxxforward.h
servercntrl.o: $(ARBHOME)/INCLUDE/dupstr.h
servercntrl.o: $(ARBHOME)/INCLUDE/gccver.h
servercntrl.o: $(ARBHOME)/INCLUDE/SigHandler.h
servercntrl.o: $(ARBHOME)/INCLUDE/smartptr.h
servercntrl.o: $(ARBHOME)/INCLUDE/test_global.h
servercntrl.o: $(ARBHOME)/INCLUDE/ut_valgrinded.h
# libraries needed to link against SERVERCNTRL/SERVERCNTRL.a
lib/libARBDB.so
# it does not matter which client.a is linked
# (e.g. arb_ntree only links PROBE_COM/client.a, so we always use that one)
PROBE_COM/client.a
// ============================================================= //
// //
// File : servercntrl.cxx //
// Purpose : //
// //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ============================================================= //
#include <servercntrl.h>
#include <client_privat.h>
#include <client.h>
#include <arbdb.h>
#include <arb_file.h>
#include <arb_sleep.h>
#include <ut_valgrinded.h>
/* The following lines go to servercntrl.h
* edit here, not there!!
* call 'make proto' to update
*/
// AISC_MKPT_PROMOTE:#ifndef ARBDB_BASE_H
// AISC_MKPT_PROMOTE:#include <arbdb_base.h>
// AISC_MKPT_PROMOTE:#endif
// AISC_MKPT_PROMOTE:
// AISC_MKPT_PROMOTE:struct arb_params {
// AISC_MKPT_PROMOTE: char *species_name;
// AISC_MKPT_PROMOTE: char *extended_name;
// AISC_MKPT_PROMOTE: char *alignment;
// AISC_MKPT_PROMOTE: char *default_file;
// AISC_MKPT_PROMOTE: char *field;
// AISC_MKPT_PROMOTE: const char *field_default;
// AISC_MKPT_PROMOTE:
// AISC_MKPT_PROMOTE: int read_only;
// AISC_MKPT_PROMOTE:
// AISC_MKPT_PROMOTE: char *job_server;
// AISC_MKPT_PROMOTE: char *db_server;
// AISC_MKPT_PROMOTE: char *mgr_server;
// AISC_MKPT_PROMOTE: char *pt_server;
// AISC_MKPT_PROMOTE:
// AISC_MKPT_PROMOTE: char *tcp;
// AISC_MKPT_PROMOTE:};
#define TRIES 1
static struct gl_struct {
aisc_com *link;
AISC_Object com;
gl_struct()
: link(0), com(0x10000*1) // faked type id (matches main object)
{ }
} glservercntrl;
char *prefixSSH(const char *host, const char *command, int async) {
/* 'host' is a hostname or 'hostname:port' (where hostname may be an IP)
'command' is the command to be executed
if 'async' is 1 -> append '&'
returns a SSH system call for foreign host or
a direct system call for the local machine
*/
char *result = 0;
char asyncChar = " &"[!!async];
if (host && host[0]) {
const char *hostPort = strchr(host, ':');
char *hostOnly = GB_strpartdup(host, hostPort ? hostPort-1 : 0);
if (!GB_host_is_local(hostOnly)) {
result = GBS_global_string_copy("ssh %s -n '%s' %c", hostOnly, command, asyncChar);
}
free(hostOnly);
}
if (!result) {
result = GBS_global_string_copy("(%s) %c", command, asyncChar);
}
return result;
}
GB_ERROR arb_start_server(const char *arb_tcp_env, int do_sleep)
{
const char *tcp_id;
GB_ERROR error = 0;
if (!(tcp_id = GBS_read_arb_tcp(arb_tcp_env))) {
error = GB_export_errorf("Entry '%s' in $(ARBHOME)/lib/arb_tcp.dat not found", arb_tcp_env);
}
else {
const char *server = strchr(tcp_id, 0) + 1;
char *serverparams = 0;
/* concatenate all params behind server
Note : changed behavior on 2007/Mar/09 -- ralf
serverparams now is one space if nothing defined in arb_tcp.dat
(previously was same as 'server' - most likely a bug)
*/
{
const char *param = strchr(server, 0)+1;
size_t plen = strlen(param);
size_t alllen = 0;
while (plen) {
param += plen+1;
alllen += plen+1;
plen = strlen(param);
}
serverparams = (char*)malloc(alllen+1);
{
char *sp = serverparams;
param = strchr(server, 0)+1;
plen = strlen(param);
if (!plen) sp++;
else do {
memcpy(sp, param, plen);
sp[plen] = ' ';
sp += plen+1;
param += plen+1;
plen = strlen(param);
} while (plen);
sp[-1] = 0;
}
}
{
char *command = 0;
if (*tcp_id == ':') { // local mode
command = GBS_global_string_copy("%s %s -T%s &", server, serverparams, tcp_id);
make_valgrinded_call(command);
}
else {
const char *port = strchr(tcp_id, ':');
if (!port) {
error = GB_export_errorf("Error: Missing ':' in line '%s' file $(ARBHOME)/lib/arb_tcp.dat", arb_tcp_env);
}
else {
char *remoteCommand = GBS_global_string_copy("$ARBHOME/bin/%s %s -T%s", server, serverparams, port);
make_valgrinded_call(remoteCommand);
command = prefixSSH(tcp_id, remoteCommand, 1);
free(remoteCommand);
}
}
if (!error) {
error = GBK_system(command);
if (do_sleep) GB_sleep(5, SEC);
}
free(command);
}
free(serverparams);
}
return error;
}
static GB_ERROR arb_wait_for_server(const char *arb_tcp_env, const char *tcp_id, int magic_number, struct gl_struct *serverctrl, int wait) {
GB_ERROR error = NULL;
serverctrl->link = aisc_open(tcp_id, serverctrl->com, magic_number, &error);
if (!error && !serverctrl->link) { // no server running -> start one
error = arb_start_server(arb_tcp_env, 0);
while (!error && !serverctrl->link && wait) {
GB_sleep(1, SEC);
wait--;
if ((wait%10) == 0 && wait>0) {
printf("Waiting for server '%s' to come up (%i seconds left)\n", arb_tcp_env, wait);
}
serverctrl->link = aisc_open(tcp_id, serverctrl->com, magic_number, &error);
}
}
return error;
}
GB_ERROR arb_look_and_start_server(long magic_number, const char *arb_tcp_env) {
GB_ERROR error = 0;
const char *tcp_id = GBS_read_arb_tcp(arb_tcp_env);
const char *arb_tcp_dat = "$(ARBHOME)/lib/arb_tcp.dat";
if (!tcp_id) {
error = GBS_global_string("Entry '%s' not found in %s", arb_tcp_env, arb_tcp_dat);
}
else {
const char *file = GBS_scan_arb_tcp_param(tcp_id, "-d"); // find parameter behind '-d'
if (!file) {
error = GBS_global_string("Parameter -d missing for entry '%s' in %s", arb_tcp_env, arb_tcp_dat);
}
else {
if (strcmp(file, "!ASSUME_RUNNING") == 0) {
// assume pt-server is running on a host, w/o access to common network drive
// i.e. we cannot check for the existence of the database file
}
else if (GB_size_of_file(file) <= 0) {
if (strncmp(arb_tcp_env, "ARB_NAME_SERVER", 15) == 0) {
char *dir = strdup(file);
char *lastSlash = strrchr(dir, '/');
if (lastSlash) {
lastSlash[0] = 0; // cut off file
{
const char *copy_cmd = GBS_global_string("cp %s/names.dat.template %s", dir, file);
error = GBK_system(copy_cmd);
}
if (!error && GB_size_of_file(file) <= 0) {
error = GBS_global_string("Cannot copy nameserver template (%s/names.dat.template missing?)", dir);
}
}
else {
error = GBS_global_string("Can't determine directory from '%s'", dir);
}
free(dir);
}
else if (strncmp(arb_tcp_env, "ARB_PT_SERVER", 13) == 0) {
const char *nameOnly = strrchr(file, '/');
if (!nameOnly) nameOnly = file;
error = GBS_global_string("PT_server '%s' has not been created yet.\n"
" To create it follow these steps:\n"
" 1. Start ARB on the whole database you want to use for probe match/design\n"
" 2. Go to ARB_NTREE/Probes/PT_SERVER Admin\n"
" 3. Select '%s' and press BUILD SERVER\n"
" 4. Wait (up to hours, depending on your DB size)\n"
" 5. Meanwhile read the help file: PT_SERVER: What Why and How",
file, nameOnly);
}
else {
error = GBS_global_string("The file '%s' is missing. \nUnable to start %s", file, arb_tcp_env);
}
}
}
if (!error) {
error = arb_wait_for_server(arb_tcp_env, tcp_id, magic_number, &glservercntrl, 20);
if (!error) {
if (!glservercntrl.link) { // couldn't start server
error = // |
"ARB has problems to start a server! Possible reasons may be one\n"
"or several of the following list:\n"
"- the tcp_id (socket number) is already used by another program\n"
" (doesnt apply to user-specific PTSERVERs; check $ARBHOME/lib/arb_tcp.dat versus /etc/services)\n"
"- the server exited with error or has crashed.\n"
" In case of PTSERVER, the failure might be caused by:\n"
" - missing database in $ARBHOME/lib/pts/* (solution: update ptserver database)\n"
" - wrong permissions of $ARBHOME/lib/pts/* (no read access)\n"
" If you recently installed a new arb version, arb will continue\n"
" to use your previous 'arb_tcp.dat', which might be out-of-date.\n"
" Backup and remove it, then restart ARB. If it works now,\n"
" compare your old 'arb_tcp.dat' with the new one for changes.\n"
"- When using remote servers: login or network problems\n"
;
}
else {
aisc_close(glservercntrl.link, glservercntrl.com);
glservercntrl.link = 0;
}
}
}
}
return error;
}
GB_ERROR arb_look_and_kill_server(int magic_number, const char *arb_tcp_env) {
const char *tcp_id;
GB_ERROR error = 0;
if (!(tcp_id = GBS_read_arb_tcp(arb_tcp_env))) {
error = GB_export_errorf("Missing line '%s' in $(ARBHOME)/lib/arb_tcp.dat:", arb_tcp_env);
}
else {
const char *server = strchr(tcp_id, 0)+1;
glservercntrl.link = aisc_open(tcp_id, glservercntrl.com, magic_number, &error);
if (glservercntrl.link) {
aisc_close(glservercntrl.link, glservercntrl.com);
glservercntrl.link = 0;
const char *command = GBS_global_string("%s -kill -T%s &", server, tcp_id);
if (system(command) != 0) {
error = GBS_global_string("Failed to execute '%s'", command);
}
}
else {
error = "Server is not running";
}
}
return error;
}
void arb_print_server_params() {
printf("General server parameters (some maybe unused by this server):\n"
" -s<name> sets species name to '<name>'\n"
" -e<name> sets extended name to '<name>'\n"
" -a<ali> sets alignment to '<ali>'\n"
" -d<file> sets default file to '<file>'\n"
" -f<field>=<def> sets DB field to '<field>' (using <def> as default)\n"
" -r read-only mode\n"
" -D<server> sets DB-server to '<server>' [default = ':']\n"
" -J<server> sets job-server to '<server>' [default = 'ARB_JOB_SERVER']\n"
" -M<server> sets MGR-server to '<server>' [default = 'ARB_MGR_SERVER']\n"
" -P<server> sets PT-server to '<server>' [default = 'ARB_PT_SERVER']\n"
" -T<[host]:port> sets TCP connection to '<[host]:port>'\n"
);
}
arb_params *arb_trace_argv(int *argc, const char **argv)
{
int s, d;
arb_params *erg = (arb_params *)calloc(sizeof(arb_params), 1);
erg->db_server = strdup(":");
erg->job_server = strdup("ARB_JOB_SERVER");
erg->mgr_server = strdup("ARB_MGR_SERVER");
erg->pt_server = strdup("ARB_PT_SERVER");
for (s=d=0; s<*argc; s++) {
if (argv[s][0] == '-') {
switch (argv[s][1]) {
case 's': erg->species_name = strdup(argv[s]+2); break;
case 'e': erg->extended_name = strdup(argv[s]+2); break;
case 'a': erg->alignment = strdup(argv[s]+2); break;
case 'd': erg->default_file = strdup(argv[s]+2); break;
case 'f': {
char *eq;
erg->field = strdup(argv[s]+2);
eq = strchr(erg->field, '=');
if (eq) {
erg->field_default = eq+1;
eq[0] = 0;
}
else {
erg->field_default = 0; // this is illegal - error handling done in caller
}
break;
}
case 'r': erg->read_only = 1; break;
case 'J': freedup(erg->job_server, argv[s]+2); break;
case 'D': freedup(erg->db_server, argv[s]+2); break;
case 'M': freedup(erg->mgr_server, argv[s]+2); break;
case 'P': freedup(erg->pt_server, argv[s]+2); break;
case 'T': {
const char *ipport = argv[s]+2;
if (ipport[0] == ':' &&
ipport[1] >= '0' && ipport[1] <= '9') { // port only -> assume localhost
erg->tcp = GBS_global_string_copy("localhost%s", ipport);
}
else {
erg->tcp = strdup(ipport);
}
break;
}
default:
argv[d++] = argv[s];
break;
}
}
else {
argv[d++] = argv[s];
}
}
*argc = d;
return erg;
}
void free_arb_params(arb_params *params) {
free(params->species_name);
free(params->extended_name);
free(params->alignment);
free(params->default_file);
free(params->field);
free(params->job_server);
free(params->db_server);
free(params->mgr_server);
free(params->pt_server);
free(params->tcp);
free(params);
}
// --------------------------------------------------------------------------------
#if defined(UNIT_TESTS)
// If you need tests in AISC_COM/C/client.c, put them here instead.
#include <test_unit.h>
void TEST_servercntrl() {
// TEST_EXPECT(0);
}
#endif // UNIT_TESTS
/* This file is generated by aisc_mkpt.
* Any changes you make here will be overwritten later!
*/
#ifndef SERVERCNTRL_H
#define SERVERCNTRL_H
/* servercntrl.cxx */
#ifndef ARBDB_BASE_H
#include <arbdb_base.h>
#endif
struct arb_params {
char *species_name;
char *extended_name;
char *alignment;
char *default_file;
char *field;
const char *field_default;
int read_only;
char *job_server;
char *db_server;
char *mgr_server;
char *pt_server;
char *tcp;
};
char *prefixSSH(const char *host, const char *command, int async);
GB_ERROR arb_start_server(const char *arb_tcp_env, int do_sleep);
GB_ERROR arb_look_and_start_server(long magic_number, const char *arb_tcp_env);
GB_ERROR arb_look_and_kill_server(int magic_number, const char *arb_tcp_env);
void arb_print_server_params(void);
arb_params *arb_trace_argv(int *argc, const char **argv);
void free_arb_params(arb_params *params);
#else
#error servercntrl.h included twice
#endif /* SERVERCNTRL_H */
// ================================================================= //
// //
// File : cb.h //
// Purpose : callback //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in September 2010 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ================================================================= //
#ifndef CB_H
#define CB_H
#ifndef ARBDB_BASE_H
#include <arbdb_base.h>
#endif
class AW_root;
class AW_window;
class AW_awar;
// generic callback parameter (used like a void*)
typedef long AW_CL; // client data (casted from pointer or value)
// Note:
// most callbacks below are considered obsolete (as soon as #432 is completed)
// They are mostly used to cast functions; better use make....Callback-wrappers
// AW_root callbacks
typedef void (*AW_RCB2)(AW_root*, AW_CL, AW_CL);
typedef void (*AW_RCB1)(AW_root*, AW_CL);
typedef void (*AW_RCB0)(AW_root*);
typedef AW_RCB2 AW_RCB;
// AW_awar callbacks
typedef AW_RCB2 Awar_CB2;
typedef AW_RCB1 Awar_CB1;
typedef AW_RCB0 Awar_CB0;
typedef AW_RCB Awar_CB;
// AW_window callbacks
typedef void (*AW_CB2)(AW_window*, AW_CL, AW_CL);
typedef void (*AW_CB1)(AW_window*, AW_CL);
typedef void (*AW_CB0)(AW_window*);
typedef AW_CB2 AW_CB;
// simplest callback flavours of each type
typedef AW_window *(*CreateWindowCallbackSimple)(AW_root*); // use makeCreateWindowCallback if you need parameters
typedef AW_RCB0 RootCallbackSimple; // use makeRootCallback if you need parameters
typedef AW_CB0 WindowCallbackSimple; // use makeWindowCallback if you need parameters
// ---------------------------
// typesafe callbacks
#ifndef CBTYPES_H
#include <cbtypes.h>
#endif
// @@@ when gtk port is back to trunk, the definition of some of these cb-types may be moved into WINDOW
DECLARE_CBTYPE_FVV_AND_BUILDERS(RootCallback, void, AW_root*); // generates makeRootCallback
DECLARE_CBTYPE_FVV_AND_BUILDERS(TimedCallback, unsigned, AW_root*); // generates makeTimedCallback (return value: 0->do not call again, else: call again after XXX ms)
DECLARE_CBTYPE_FVV_AND_BUILDERS(WindowCallback, void, AW_window*); // generates makeWindowCallback
DECLARE_CBTYPE_FVV_AND_BUILDERS(CreateWindowCallback, AW_window*, AW_root*); // generates makeCreateWindowCallback
DECLARE_CBTYPE_FVF_AND_BUILDERS(DatabaseCallback, void, GBDATA*, GB_CB_TYPE); // generates makeDatabaseCallback
DECLARE_CBTYPE_FFV_AND_BUILDERS(TreeAwarCallback, void, AW_awar*, bool); // generates makeTreeAwarCallback
#else
#error cb.h included twice
#endif // CB_H
// =============================================================== //
// //
// File : Translate.hxx //
// Purpose : //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in June 2006 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// =============================================================== //
// ================================================================ //
// //
// File : cb_base.h //
// Purpose : base types for interfaces //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in November 2013 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ================================================================ //
#ifndef TRANSLATE_HXX
#define TRANSLATE_HXX
#ifndef CB_BASE_H
#define CB_BASE_H
#ifndef ARBDB_BASE_H
#include <arbdb_base.h>
#endif
GB_ERROR AWT_getTranslationInfo(GBDATA *gb_species, int& arb_transl_table, int &codon_start);
GB_ERROR AWT_saveTranslationInfo(GBDATA *gb_species, int arb_transl_table, int codon_start);
GB_ERROR AWT_removeTranslationInfo(GBDATA *gb_species);
int AWT_pro_a_nucs_convert(int arb_code_nr, char *data, size_t size, size_t pos, bool translate_all, bool create_start_codon, bool append_stop_codon, int *translatedSize);
typedef struct Unfixed_cb_parameter *UNFIXED; // Unfixed_cb_parameter does not exist (intentionally!)
#else
#error Translate.hxx included twice
#endif // TRANSLATE_HXX
#error cb_base.h included twice
#endif // CB_BASE_H
// ============================================================== //
// //
// File : cbtypes.h //
// Purpose : generic cb types //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in August 2011 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ============================================================== //
#ifndef CBTYPES_H
#define CBTYPES_H
#ifndef CB_BASE_H
#include "cb_base.h"
#endif
#ifndef TTYPES_H
#include <ttypes.h>
#endif
#ifndef STATIC_ASSERT_H
#include <static_assert.h>
#endif
#ifndef SMARTPTR_H
#include <smartptr.h>
#endif
// ---------------------------------
// function type inspection
template<typename RT, typename P1, typename P2, typename P3>
struct Function {
enum { NumParams = 3 };
typedef RT (*Type)(P1,P2,P3);
typedef RT ResultType;
};
template<typename RT, typename P1, typename P2>
struct Function<RT, P1, P2, void> {
enum { NumParams = 2 };
typedef RT (*Type)(P1,P2);
};
template<typename RT, typename P1>
struct Function<RT, P1, void, void> {
enum { NumParams = 1 };
typedef RT (*Type)(P1);
};
template<typename RT>
struct Function<RT, void, void, void> {
enum { NumParams = 0 };
typedef RT (*Type)();
};
// ---------------------------
// forward parameters
template<typename T>
struct ForwardParamT {
typedef typename IfThenElseType< TypeT<T>::IsClassT,
typename TypeOp<T>::RefConstT,
typename TypeOp<T>::ArgT >::ResultType Type;
};
template<typename T>
struct ForwardParamT<T*> {
typedef typename TypeOp<T>::ArgT *Type;
};
template<> class ForwardParamT<void> { class Unused {}; public: typedef Unused Type; };
// ------------------------------
// const parameter types
template<typename T>
struct ConstParamT {
typedef typename IfThenElseType< TypeT<T>::IsClassT,
typename TypeOp<T>::RefConstT,
typename TypeOp<T>::ConstT >::ResultType Type;
};
template<typename T>
struct ConstParamT<T*> {
typedef typename TypeOp<T>::ConstT *Type;
};
template<> class ConstParamT<void> { class Unused {}; public: typedef Unused Type; };
// ------------------------------------
// forbid some parameter types
template<typename T> class AW_CL_castableType { public: static AW_CL cast_to_AW_CL(const T& t) { return (AW_CL)t; } };
#define INVALID_CB_PARAM_TYPE(TYPE) template<> class AW_CL_castableType<TYPE> { }
INVALID_CB_PARAM_TYPE(void);
INVALID_CB_PARAM_TYPE(double);
INVALID_CB_PARAM_TYPE(float);
#undef INVALID_CB_PARAM_TYPE
// -----------------------
// typed callback
template<typename RT, typename P1 = void, typename P2 = void, typename P3 = void>
struct StrictlyTypedCallback {
typedef typename Function<RT,P1,P2,P3>::Type FuncType;
private:
typedef typename ForwardParamT<P1>::Type FP1;
typedef typename ForwardParamT<P2>::Type FP2;
typedef typename ForwardParamT<P3>::Type FP3;
FuncType cb;
public:
enum { NumParams = Function<RT,P1,P2,P3>::NumParams };
StrictlyTypedCallback(FuncType CB) : cb(CB) {}
RT operator()(FP1 p1, FP2 p2, FP3 p3) const { return cb(p1, p2, p3); }
RT operator()(FP1 p1, FP2 p2) const { return cb(p1, p2); }
RT operator()(FP1 p1) const { return cb(p1); }
RT operator()() const { return cb(); }
bool equals(const StrictlyTypedCallback& other) const { return cb == other.cb; }
AW_CL get_cb() const { return (AW_CL)cb; }
static StrictlyTypedCallback make_cb(AW_CL cb_) { return StrictlyTypedCallback((FuncType)cb_); }
bool is_set() const { return cb != 0; }
bool operator < (const StrictlyTypedCallback& other) const { return cb < other.cb; }
bool operator == (const StrictlyTypedCallback& other) const { return cb == other.cb; }
};
// ---------------------
// CallbackData
template<typename P1, typename P2>
struct CallbackData {
P1 p1;
P2 p2;
typedef void (*CallbackDataDeallocator)(P1 p1, P2 p2);
CallbackDataDeallocator dealloc;
CallbackData(P1 p1_, P2 p2_) : p1(p1_), p2(p2_), dealloc(NULL) {}
CallbackData(P1 p1_, P2 p2_, CallbackDataDeallocator dealloc_) : p1(p1_), p2(p2_), dealloc(dealloc_) {}
~CallbackData() { if (dealloc) dealloc(p1, p2); }
bool operator < (const CallbackData& other) const {
return p1<other.p1 || (p1 == other.p1 && (p2< other.p2 || (p2 == other.p2 && dealloc<other.dealloc)));
}
bool operator == (const CallbackData& other) const {
return p1 == other.p1 && p2 == other.p2 && dealloc == other.dealloc;
}
};
typedef CallbackData<AW_CL,AW_CL> UntypedCallbackData;
// ------------------------------
// casted callback types
template<typename RT, typename FIXED>
struct Callback_FVV { // FVV stands for arguments (FIXED, VARIABLE, VARIABLE)
typedef StrictlyTypedCallback<RT,FIXED,AW_CL,AW_CL> Signature;
private:
Signature cb;
SmartPtr<UntypedCallbackData> cd;
public:
Callback_FVV(Signature CB, AW_CL P1, AW_CL P2) : cb(CB), cd(new UntypedCallbackData(P1, P2)) {}
Callback_FVV(Signature CB, UntypedCallbackData::CallbackDataDeallocator dealloc, AW_CL P1, AW_CL P2) : cb(CB), cd(new UntypedCallbackData(P1, P2, dealloc)) {}
RT operator()(FIXED fixed) const { return cb(fixed, cd->p1, cd->p2); }
bool operator < (const Callback_FVV& other) const { return cb<other.cb || (cb == other.cb && *cd<*other.cd); }
bool operator == (const Callback_FVV& other) const { return cb == other.cb && *cd == *other.cd; }
bool same_function_as(const Callback_FVV& other) const { return cb == other.cb; }
AW_CL callee() const { return cb.get_cb(); } // @@@ only intermediate - remove later
AW_CL inspect_CD1() const { return cd->p1; } // @@@ only intermediate - remove later
AW_CL inspect_CD2() const { return cd->p2; } // @@@ only intermediate - remove later
};
template<typename RT, typename F1, typename F2>
struct Callback_FFV { // FFV stands for arguments (FIXED, FIXED, VARIABLE)
typedef StrictlyTypedCallback<RT,F1,F2,AW_CL> Signature;
private:
typedef CallbackData<AW_CL, AW_CL> FFV_CallbackData; // 2nd AW_CL is unused
Signature cb;
SmartPtr<FFV_CallbackData> cd;
public:
Callback_FFV(Signature CB, AW_CL P)
: cb(CB),
cd(new FFV_CallbackData(P, 0))
{}
RT operator()(F1 f1, F2 f2) const { return cb(f1, f2, cd->p1); }
};
template<typename RT, typename F1, typename F2>
struct Callback_FVF { // FVF stands for arguments (FIXED, VARIABLE, FIXED)
typedef StrictlyTypedCallback<RT,F1,AW_CL,F2> SigP1;
typedef StrictlyTypedCallback<RT,F1,F2,void> SigP0F12;
typedef StrictlyTypedCallback<RT,F2,void,void> SigP0F2;
private:
enum funtype { ST_P0F12, ST_P0F2, ST_P1 }; // Signature type
typedef CallbackData<AW_CL,funtype> FVF_CallbackData;
AW_CL cb; // has one of the above Signatures
SmartPtr<FVF_CallbackData> cd; // cd->p2 cannot be used by clients and is used to select Signature of 'cb'
funtype get_funtype() const { return cd->p2; }
public:
Callback_FVF(SigP0F12 CB) : cb(CB.get_cb()), cd(new FVF_CallbackData(0, ST_P0F12)) {}
Callback_FVF(SigP0F2 CB) : cb(CB.get_cb()), cd(new FVF_CallbackData(0, ST_P0F2)) {}
Callback_FVF(SigP1 CB, AW_CL P1) : cb(CB.get_cb()), cd(new FVF_CallbackData(P1, ST_P1)) {}
Callback_FVF(SigP1 CB, UntypedCallbackData::CallbackDataDeallocator dealloc, AW_CL P1)
: cb(CB.get_cb()), cd(new FVF_CallbackData(P1, ST_P1, (typename FVF_CallbackData::CallbackDataDeallocator)dealloc)) {}
RT operator()(F1 f1, F2 f2) const {
funtype ft = get_funtype();
if (ft == ST_P0F12) return SigP0F12::make_cb(cb)(f1, f2);
if (ft == ST_P0F2) return SigP0F2::make_cb(cb)(f2);
arb_assert(ft == ST_P1);
return SigP1::make_cb(cb)(f1, cd->p1, f2);
}
bool operator < (const Callback_FVF& other) const { return cb<other.cb || (cb == other.cb && *cd<*other.cd); }
bool operator == (const Callback_FVF& other) const { return cb == other.cb && *cd == *other.cd; }
bool same_function_as(const Callback_FVF& other) const { return cb == other.cb; }
AW_CL callee() const { return cb; } // @@@ only intermediate - remove later
AW_CL inspect_CD1() const { return cd->p1; } // @@@ only intermediate - remove later
AW_CL inspect_CD2() const { return cd->p2; } // @@@ only intermediate - remove later
};
// ---------------------------
// convenience macros
#define CASTABLE_TO_AW_CL(TYPE) (sizeof(TYPE) <= sizeof(AW_CL))
#define CAST_TO_AW_CL(TYPE,PARAM) AW_CL_castableType<TYPE>::cast_to_AW_CL(PARAM)
#define CONST_PARAM_T(T) typename ConstParamT<T>::Type
#define CBTYPE_FVV_BUILDER_NP(BUILDER,CB,RESULT,FIXED,SIG) \
inline CB BUILDER(RESULT (*cb)(FIXED)) { \
return CB((SIG)cb, 0, 0); \
}
#define CBTYPE_FVV_BUILDER_P1(BUILDER,CB,RESULT,FIXED,SIG,P1,P1fun) \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(FIXED, P1fun), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, CAST_TO_AW_CL(P1,p1), 0); \
} \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(FIXED, P1fun), \
void (*dealloc)(P1), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, (UntypedCallbackData::CallbackDataDeallocator)dealloc, CAST_TO_AW_CL(P1,p1), 0); \
}
#define CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,P1fun,P2fun) \
template<typename P1, typename P2> \
inline CB BUILDER(RESULT (*cb)(FIXED, P1fun, P2fun), \
P1 p1, P2 p2) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1) && CASTABLE_TO_AW_CL(P2)); \
return CB((SIG)cb, CAST_TO_AW_CL(P1,p1), CAST_TO_AW_CL(P2,p2)); \
} \
template<typename P1, typename P2> \
inline CB BUILDER(RESULT (*cb)(FIXED, P1fun, P2fun), \
void (*dealloc)(P1,P2), P1 p1, P2 p2) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1) && CASTABLE_TO_AW_CL(P2)); \
return CB((SIG)cb, (UntypedCallbackData::CallbackDataDeallocator)dealloc, CAST_TO_AW_CL(P1,p1), CAST_TO_AW_CL(P2,p2)); \
}
#define CBTYPE_FVV_BUILDER_NP12(BUILDER,CB,RESULT,FIXED,SIG,P1,P2) \
CBTYPE_FVV_BUILDER_NP(BUILDER,CB,RESULT,FIXED,SIG); \
CBTYPE_FVV_BUILDER_P1(BUILDER,CB,RESULT,FIXED,SIG,P1,P1); \
CBTYPE_FVV_BUILDER_P1(BUILDER,CB,RESULT,FIXED,SIG,P1,CONST_PARAM_T(P1)); \
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,P1,P2); \
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,P1,CONST_PARAM_T(P2)); \
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,CONST_PARAM_T(P1),P2); \
CBTYPE_FVV_BUILDER_P1P2(BUILDER,CB,RESULT,FIXED,SIG,P1,P2,CONST_PARAM_T(P1),CONST_PARAM_T(P2))
#define CBTYPE_FVV_BUILDER_TEMPLATES(BUILDER,CB,RESULT,FIXED,SIG) \
inline CB BUILDER(RESULT (*cb)()) { \
return CB((SIG)cb, 0, 0); \
} \
CBTYPE_FVV_BUILDER_NP12(BUILDER,CB,RESULT,FIXED,SIG,P1,P2); \
CBTYPE_FVV_BUILDER_NP12(BUILDER,CB,RESULT,UNFIXED,SIG,P1,P2)
#define CBTYPE_FVV_BUILDER_P(BUILDER,CB,RESULT,F1,F2,SIG,P,Pfun) \
template<typename P> \
inline CB BUILDER(RESULT (*cb)(F1,F2,Pfun), P p) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P)); \
return CB((SIG)cb, CAST_TO_AW_CL(P,p)); \
} \
template<typename P> \
inline CB BUILDER(RESULT (*cb)(F1,F2,Pfun), void (*dealloc)(P), P p) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P)); \
return CB((SIG)cb, (UntypedCallbackData::CallbackDataDeallocator)dealloc, CAST_TO_AW_CL(P,p)); \
}
#define CBTYPE_FFV_BUILDER_TEMPLATES(BUILDER,CB,RESULT,F1,F2,SIG) \
inline CB BUILDER(RESULT (*cb)()) { return CB((SIG)cb, 0); } \
inline CB BUILDER(RESULT (*cb)(F1)) { return CB((SIG)cb, 0); } \
inline CB BUILDER(RESULT (*cb)(F1,F2)) { return CB((SIG)cb, 0); } \
CBTYPE_FVV_BUILDER_P(BUILDER,CB,RESULT,F1,F2,SIG,P,P); \
CBTYPE_FVV_BUILDER_P(BUILDER,CB,RESULT,F1,F2,SIG,P,CONST_PARAM_T(P))
#define CBTYPE_FVF_BUILDER_P1_F1F2(BUILDER,CB,RESULT,F1,F2,SIG,P1,P1fun) \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(F1, P1fun, F2), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, CAST_TO_AW_CL(P1,p1)); \
} \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(F1, P1fun, F2), \
void (*dealloc)(P1), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, (UntypedCallbackData::CallbackDataDeallocator)dealloc, CAST_TO_AW_CL(P1,p1)); \
}
#define CBTYPE_FVF_BUILDER_P1_F1(BUILDER,CB,RESULT,F1,SIG,P1,P1fun) \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(F1, P1fun), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, CAST_TO_AW_CL(P1,p1)); \
} \
template<typename P1> \
inline CB BUILDER(RESULT (*cb)(F1, P1fun), \
void (*dealloc)(P1), P1 p1) { \
STATIC_ASSERT(CASTABLE_TO_AW_CL(P1)); \
return CB((SIG)cb, (UntypedCallbackData::CallbackDataDeallocator)dealloc, CAST_TO_AW_CL(P1,p1)); \
}
#define CBTYPE_FVF_BUILDER_NP1(BUILDER,CB,RESULT,F1,F2,SIG,SIG01,P1) \
inline CB BUILDER(RESULT (*cb)(F1)) { return CB((SIG01)cb); } \
inline CB BUILDER(RESULT (*cb)(F1,F2)) { return CB((SIG01)cb); } \
CBTYPE_FVF_BUILDER_P1_F1F2(BUILDER,CB,RESULT,F1,F2,SIG,P1,P1); \
CBTYPE_FVF_BUILDER_P1_F1F2(BUILDER,CB,RESULT,F1,F2,SIG,P1,CONST_PARAM_T(P1)); \
CBTYPE_FVF_BUILDER_P1_F1(BUILDER,CB,RESULT,F1,SIG,P1,P1); \
CBTYPE_FVF_BUILDER_P1_F1(BUILDER,CB,RESULT,F1,SIG,P1,CONST_PARAM_T(P1))
#define CBTYPE_FVF_BUILDER_TEMPLATES(BUILDER,CB,RESULT,F1,F2,SIG,SIG01,SIG02) \
inline CB BUILDER(RESULT (*cb)()) { return CB((SIG01)cb); } \
inline CB BUILDER(RESULT (*cb)(F2)) { return CB((SIG02)cb); } \
CBTYPE_FVF_BUILDER_NP1(BUILDER,CB,RESULT,F1,F2,SIG,SIG01,P1); \
CBTYPE_FVF_BUILDER_NP1(BUILDER,CB,RESULT,UNFIXED,F2,SIG,SIG01,P1)
// declares the callback type (CBTYPE) and the makeCBTYPE() templates needed to ensure
// typecheck between callback-signature and bound parameters
#define DECLARE_CBTYPE_FVV_AND_BUILDERS(CBTYPE,RESULT,FIXED) \
typedef Callback_FVV<RESULT, FIXED> CBTYPE; \
CBTYPE_FVV_BUILDER_TEMPLATES(make##CBTYPE,CBTYPE,RESULT,FIXED, \
CBTYPE::Signature::FuncType)
#define DECLARE_CBTYPE_FFV_AND_BUILDERS(CBTYPE,RESULT,F1,F2) \
typedef Callback_FFV<RESULT,F1,F2> CBTYPE; \
CBTYPE_FFV_BUILDER_TEMPLATES(make##CBTYPE,CBTYPE,RESULT,F1,F2, \
CBTYPE::Signature::FuncType)
#define DECLARE_CBTYPE_FVF_AND_BUILDERS(CBTYPE,RESULT,F1,F2) \
typedef Callback_FVF<RESULT,F1,F2> CBTYPE; \
CBTYPE_FVF_BUILDER_TEMPLATES(make##CBTYPE,CBTYPE,RESULT,F1,F2, \
CBTYPE::SigP1::FuncType, \
CBTYPE::SigP0F12::FuncType, \
CBTYPE::SigP0F2::FuncType)
#else
#error cbtypes.h included twice
#endif // CBTYPES_H
# for variables passed from parent makefile see ../../SOURCE_TOOLS/parent_make.txt
.SUFFIXES: .o .c .cxx .depend
C_OBJECTS =
CPP_OBJECTS = \
Translate.o \
OBJECTS=$(C_OBJECTS) $(CPP_OBJECTS)
$(MAIN): $(OBJECTS)
$(LINK_STATIC_LIB) $(MAIN) $(OBJECTS)
.cxx.o:
$(A_CXX) $(cflags) $(cxxflags) -c $< $(CXX_INCLUDES) $(POST_COMPILE)
.c.o:
$(A_CC) $(cflags) -c $< $(CC_INCLUDES) $(POST_COMPILE)
clean:
rm -f $(OBJECTS) *.a
DEPENDS = $(OBJECTS:.o=.depend)
depends: $(DEPENDS)
@cat $(DEPENDS) | grep -v '^#' >>Makefile
@rm $(DEPENDS)
$(DEPENDS): depend.init
depend.init:
$(MAKEDEPEND) $(MAKEDEPENDFLAGS) 2>/dev/null # remove dependencies
.c.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
.cxx.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
# DO NOT DELETE
# Do not add dependencies manually - use 'make depend' in $ARBHOME
# For formatting issues see SOURCE_TOOLS/fix_depends.pl (from SL)
Translate.o: Translate.hxx
Translate.o: $(ARBHOME)/INCLUDE/ad_prot.h
Translate.o: $(ARBHOME)/INCLUDE/ad_t_prot.h
Translate.o: $(ARBHOME)/INCLUDE/AP_codon_table.hxx
Translate.o: $(ARBHOME)/INCLUDE/AP_pro_a_nucs.hxx
Translate.o: $(ARBHOME)/INCLUDE/arb_assert.h
Translate.o: $(ARBHOME)/INCLUDE/arb_core.h
Translate.o: $(ARBHOME)/INCLUDE/arb_error.h
Translate.o: $(ARBHOME)/INCLUDE/arb_msg.h
Translate.o: $(ARBHOME)/INCLUDE/arb_string.h
Translate.o: $(ARBHOME)/INCLUDE/arbdb.h
Translate.o: $(ARBHOME)/INCLUDE/arbdb_base.h
Translate.o: $(ARBHOME)/INCLUDE/arbdbt.h
Translate.o: $(ARBHOME)/INCLUDE/arbtools.h
Translate.o: $(ARBHOME)/INCLUDE/attributes.h
Translate.o: $(ARBHOME)/INCLUDE/cxxforward.h
Translate.o: $(ARBHOME)/INCLUDE/downcast.h
Translate.o: $(ARBHOME)/INCLUDE/dupstr.h
Translate.o: $(ARBHOME)/INCLUDE/gccver.h
Translate.o: $(ARBHOME)/INCLUDE/smartptr.h
Translate.o: $(ARBHOME)/INCLUDE/static_assert.h
Translate.o: $(ARBHOME)/INCLUDE/test_global.h
// =============================================================== //
// //
// File : AWT_translate.cxx //
// Purpose : //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in June 2006 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// =============================================================== //
#include "Translate.hxx"
#include <AP_pro_a_nucs.hxx>
#include <AP_codon_table.hxx>
#include <arbdbt.h>
#define tl_assert(cond) arb_assert(cond)
GB_ERROR AWT_saveTranslationInfo(GBDATA *gb_species, int arb_transl_table, int codon_start) {
int embl_transl_table = AWT_arb_code_nr_2_embl_transl_table(arb_transl_table);
tl_assert(codon_start >= 0 && codon_start<3); // codon_start has to be 0..2
tl_assert(embl_transl_table >= 0);
GB_ERROR error = GBT_write_string(gb_species, "transl_table", GBS_global_string("%i", embl_transl_table));
if (!error) error = GBT_write_string(gb_species, "codon_start", GBS_global_string("%i", codon_start+1));
return error;
}
GB_ERROR AWT_removeTranslationInfo(GBDATA *gb_species) {
GB_ERROR error = NULL;
GBDATA *gb_transl_table = GB_entry(gb_species, "transl_table");
if (gb_transl_table) error = GB_delete(gb_transl_table);
if (!error) {
GBDATA *gb_codon_start = GB_entry(gb_species, "codon_start");
if (gb_codon_start) error = GB_delete(gb_codon_start);
}
return error;
}
GB_ERROR AWT_getTranslationInfo(GBDATA *gb_item, int& arb_transl_table, int& codon_start) {
// looks for sub-entries 'transl_table' and 'codon_start' of species (works for genes as well)
// if found -> test for validity and translate 'transl_table' from EMBL to ARB table number
//
// returns: an error in case of problems
//
// 'arb_transl_table' is set to -1 if not found, otherwise it contains the arb table number
// 'codon_start' is set to -1 if not found, otherwise it contains the codon_start (0..2)
arb_transl_table = -1; // not found yet
codon_start = -1; // not found yet
GB_ERROR error = 0;
GBDATA *gb_transl_table = GB_entry(gb_item, "transl_table");
if (gb_transl_table) {
int embl_table = atoi(GB_read_char_pntr(gb_transl_table));
arb_transl_table = AWT_embl_transl_table_2_arb_code_nr(embl_table);
if (arb_transl_table == -1) { // ill. table
error = GBS_global_string("Illegal (or unsupported) value (%i) in 'transl_table'", embl_table);
}
}
if (!error) {
GBDATA *gb_codon_start = GB_entry(gb_item, "codon_start");
if (gb_codon_start) {
int codon_start_value = atoi(GB_read_char_pntr(gb_codon_start));
if (codon_start_value<1 || codon_start_value>3) {
error = GBS_global_string("Illegal value (%i) in 'codon_start' (allowed: 1..3)", codon_start_value);
}
else {
codon_start = codon_start_value-1; // internal value is 0..2
}
}
else if (arb_transl_table != -1) {
// default to codon_start 1
error = GBT_write_string(gb_item, "codon_start", "1");
if (!error) codon_start = 0; // internal value is 0..2
}
}
if (!error && arb_transl_table != codon_start) {
if (arb_transl_table == -1) error = "Found 'codon_start', but 'transl_table' is missing";
else if (codon_start == -1) error = "Found 'transl_table', but 'codon_start' is missing";
}
if (error) { // append species name to error message
error = GBS_global_string("%s (item='%s')", error, GBT_read_name(gb_item));
}
return error;
}
inline void memcpy3(char *dest, const char *source) {
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
}
int AWT_pro_a_nucs_convert(int arb_code_nr, char *data, size_t size, size_t pos, bool translate_all, bool create_start_codon, bool append_stop_codon, int *translatedSize) {
// if translate_all == true -> 'pos' > 1 produces a leading 'X' in protein data
// (otherwise nucleotides in front of the starting pos are simply ignored)
//
// if 'create_start_codon' is true and the first generated codon is a start codon of the used
// code, a 'M' is inserted instead of the codon
// if 'append_stop_codon' is true, the stop codon is appended as '*'. This is only done, if the last
// character not already is a stop codon. (Note: provide data with correct size)
//
// returns:
// - the translated protein sequence in 'data'
// - the length of the translated protein sequence in 'translatedSize' (if != 0)
// - number of stop-codons in translated sequence as result
arb_assert(pos <= 2);
for (char *p = data; *p; p++) {
char c = *p;
if ((c>='a') && (c<='z')) c = c+'A'-'a';
if (c=='U') c = 'T';
*p = c;
}
char buffer[4];
buffer[3] = 0;
char *dest = data;
if (pos && translate_all) {
for (char *p = data; p<data+pos; ++p) {
char c = *p;
if (c!='.' && c!='-') { // found a nucleotide
*dest++ = 'X';
break;
}
}
}
int stops = 0;
size_t i = pos;
char startCodon = 0;
const GB_HASH *t2i_hash = AWT_get_translator(arb_code_nr)->T2iHash();
if (create_start_codon) {
memcpy3(buffer, data+pos);
startCodon = AWT_is_start_codon(buffer, arb_code_nr);
}
for (char *p = data+pos; i+2<size; p+=3, i+=3) {
memcpy3(buffer, p);
int spro = (int)GBS_read_hash(t2i_hash, buffer);
int C;
if (!spro) {
C = 'X';
}
else {
if (spro == '*') stops++;
C = spro;
if (spro == 's') C = 'S';
}
*(dest++) = (char)C;
}
int tsize = dest-data;
if (tsize>0) { // at least 1 amino written
if (create_start_codon && startCodon) data[0] = startCodon;
if (append_stop_codon && dest[-1] != '*') {
*dest++ = '*';
tsize++;
}
}
dest[0] = 0;
if (translatedSize) *translatedSize = tsize;
return stops;
}
# libraries needed to link against SL/TRANSLATE/TRANSLATE.a
SL/PRONUC/PRONUC.a
# for variables passed from parent makefile see ../../SOURCE_TOOLS/parent_make.txt
.SUFFIXES: .o .c .cxx .hxx .depend
C_OBJECTS =
CPP_OBJECTS = \
TreeDisplay.o \
irstree_display.o \
TreeCallbacks.o \
OBJECTS=$(C_OBJECTS) $(CPP_OBJECTS)
$(MAIN): $(OBJECTS)
$(LINK_STATIC_LIB) $(MAIN) $(OBJECTS)
.cxx.o:
$(A_CXX) $(cflags) $(cxxflags) -c $< $(CXX_INCLUDES) $(POST_COMPILE)
.c.o:
$(A_CC) $(cflags) -c $< $(CC_INCLUDES) $(POST_COMPILE)
proto:
../../AISC_MKPTPS/aisc_mkpt -P -w TreeCallbacks.hxx TreeCallbacks.cxx >TreeCallbacks.hxx.tmp
../../SOURCE_TOOLS/mv_if_diff TreeCallbacks.hxx.tmp TreeCallbacks.hxx
clean:
rm -f $(OBJECTS) *.a
DEPENDS = $(OBJECTS:.o=.depend)
depends: $(DEPENDS)
@cat $(DEPENDS) | grep -v '^#' >>Makefile
@rm $(DEPENDS)
$(DEPENDS): depend.init
depend.init:
$(MAKEDEPEND) $(MAKEDEPENDFLAGS) 2>/dev/null # remove dependencies
.c.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
.cxx.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
# DO NOT DELETE
# Do not add dependencies manually - use 'make depend' in $ARBHOME
# For formatting issues see SOURCE_TOOLS/fix_depends.pl (from SL)
irstree_display.o: TreeDisplay.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/ad_prot.h
irstree_display.o: $(ARBHOME)/INCLUDE/ad_t_prot.h
irstree_display.o: $(ARBHOME)/INCLUDE/AliView.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/AP_sequence.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/AP_Tree.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/arb_assert.h
irstree_display.o: $(ARBHOME)/INCLUDE/arb_core.h
irstree_display.o: $(ARBHOME)/INCLUDE/arb_error.h
irstree_display.o: $(ARBHOME)/INCLUDE/arb_msg.h
irstree_display.o: $(ARBHOME)/INCLUDE/arb_string.h
irstree_display.o: $(ARBHOME)/INCLUDE/ARB_Tree.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/arbdb.h
irstree_display.o: $(ARBHOME)/INCLUDE/arbdb_base.h
irstree_display.o: $(ARBHOME)/INCLUDE/arbdbt.h
irstree_display.o: $(ARBHOME)/INCLUDE/arbtools.h
irstree_display.o: $(ARBHOME)/INCLUDE/attributes.h
irstree_display.o: $(ARBHOME)/INCLUDE/aw_base.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_color_groups.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_device.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_device_click.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_keysym.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_position.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/aw_window.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/awt_canvas.hxx
irstree_display.o: $(ARBHOME)/INCLUDE/cb.h
irstree_display.o: $(ARBHOME)/INCLUDE/cb_base.h
irstree_display.o: $(ARBHOME)/INCLUDE/cbtypes.h
irstree_display.o: $(ARBHOME)/INCLUDE/cxxforward.h
irstree_display.o: $(ARBHOME)/INCLUDE/downcast.h
irstree_display.o: $(ARBHOME)/INCLUDE/dupstr.h
irstree_display.o: $(ARBHOME)/INCLUDE/gccver.h
irstree_display.o: $(ARBHOME)/INCLUDE/nds.h
irstree_display.o: $(ARBHOME)/INCLUDE/RootedTree.h
irstree_display.o: $(ARBHOME)/INCLUDE/smartptr.h
irstree_display.o: $(ARBHOME)/INCLUDE/static_assert.h
irstree_display.o: $(ARBHOME)/INCLUDE/test_global.h
irstree_display.o: $(ARBHOME)/INCLUDE/ttypes.h
TreeCallbacks.o: TreeCallbacks.hxx
TreeCallbacks.o: TreeDisplay.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/ad_prot.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/ad_t_prot.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/AliView.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/AP_sequence.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/AP_Tree.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arb_assert.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arb_core.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arb_error.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arb_msg.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arb_string.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/ARB_Tree.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arbdb.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arbdb_base.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arbdbt.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/arbtools.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/attributes.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_advice.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_awar.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_awar_defs.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_awars.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_base.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_color_groups.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_device.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_device_click.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_keysym.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_msg.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_position.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_root.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/aw_window.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/awt_canvas.hxx
TreeCallbacks.o: $(ARBHOME)/INCLUDE/cb.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/cb_base.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/cbtypes.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/cxxforward.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/downcast.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/dupstr.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/gccver.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/mode_text.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/RootedTree.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/smartptr.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/static_assert.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/test_global.h
TreeCallbacks.o: $(ARBHOME)/INCLUDE/ttypes.h
TreeDisplay.o: ../../WINDOW/aw_common.hxx
TreeDisplay.o: TreeDisplay.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/ad_prot.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/ad_t_prot.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/AliView.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/AP_sequence.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/AP_Tree.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_assert.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_core.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_defs.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_diff.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_error.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_global_defs.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_msg.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_strarray.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arb_string.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/ARB_Tree.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/arbdb.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arbdb_base.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arbdbt.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/arbtools.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/attributes.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_awar.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_awar_defs.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_awars.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_base.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_color_groups.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_device.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_device_click.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_keysym.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_msg.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_position.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_preset.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_question.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_root.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/aw_window.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/awt_attributes.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/awt_canvas.hxx
TreeDisplay.o: $(ARBHOME)/INCLUDE/cb.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/cb_base.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/cbtypes.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/cxxforward.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/downcast.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/dupstr.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/gccver.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/nds.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/RootedTree.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/smartptr.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/static_assert.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/test_global.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/test_unit.h
TreeDisplay.o: $(ARBHOME)/INCLUDE/ttypes.h
This diff is collapsed.
/* This file is generated by aisc_mkpt.
* Any changes you make here will be overwritten later!
*/
#ifndef TREECALLBACKS_HXX
#define TREECALLBACKS_HXX
/* TreeCallbacks.cxx */
#ifndef TREEDISPLAY_HXX
#include <TreeDisplay.hxx>
#endif
void nt_mode_event(UNFIXED, AWT_canvas *ntw, AWT_COMMAND_MODE mode);
void NT_mark_all_cb(UNFIXED, AWT_canvas *ntw, int mark_mode);
void NT_insert_mark_submenus(AW_window_menu_modes *awm, AWT_canvas *ntw, int insert_as_submenu);
void NT_group_tree_cb(UNFIXED, AWT_canvas *ntw);
void NT_group_not_marked_cb(UNFIXED, AWT_canvas *ntw);
void NT_group_terminal_cb(UNFIXED, AWT_canvas *ntw);
void NT_ungroup_all_cb(UNFIXED, AWT_canvas *ntw);
void NT_insert_color_collapse_submenu(AW_window_menu_modes *awm, AWT_canvas *ntree_canvas);
GB_ERROR NT_with_displayed_tree_do(AWT_canvas *ntw, bool (*displayed_tree_cb)(RootedTree *tree, GB_ERROR& error));
void NT_resort_tree_cb(UNFIXED, AWT_canvas *ntw, TreeOrder order);
void NT_reset_lzoom_cb(UNFIXED, AWT_canvas *ntw);
void NT_reset_pzoom_cb(UNFIXED, AWT_canvas *ntw);
void NT_set_tree_style(UNFIXED, AWT_canvas *ntw, AP_tree_display_type type);
void NT_remove_leafs(UNFIXED, AWT_canvas *ntw, AWT_RemoveType mode);
void NT_remove_bootstrap(UNFIXED, AWT_canvas *ntw);
void NT_toggle_bootstrap100(UNFIXED, AWT_canvas *ntw);
void NT_reset_branchlengths(UNFIXED, AWT_canvas *ntw);
void NT_multifurcate_tree(AWT_canvas *ntw, const RootedTree ::multifurc_limits& below);
void NT_move_boot_branch(UNFIXED, AWT_canvas *ntw, int direction);
void NT_scale_tree(UNFIXED, AWT_canvas *ntw);
void NT_jump_cb(UNFIXED, AWT_canvas *ntw, AP_tree_jump_type jumpType);
void TREE_auto_jump_cb(UNFIXED, AWT_canvas *ntw);
void NT_reload_tree_event(AW_root *awr, AWT_canvas *ntw, bool expose);
void TREE_recompute_cb(UNFIXED, AWT_canvas *ntw);
void NT_reinit_treetype(UNFIXED, AWT_canvas *ntw);
void NT_remove_species_in_tree_from_hash(AP_tree *tree, GB_HASH *hash);
#else
#error TreeCallbacks.hxx included twice
#endif /* TREECALLBACKS_HXX */
This diff is collapsed.
// =============================================================== //
// //
// File : TreeDisplay.hxx //
// Purpose : //
// //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// =============================================================== //
#ifndef TREEDISPLAY_HXX
#define TREEDISPLAY_HXX
#ifndef AP_TREE_HXX
#include <AP_Tree.hxx>
#endif
#ifndef AWT_CANVAS_HXX
#include <awt_canvas.hxx>
#endif
#define td_assert(cond) arb_assert(cond)
#define AWAR_DTREE_BASELINEWIDTH "awt/dtree/baselinewidth"
#define AWAR_DTREE_VERICAL_DIST "awt/dtree/verticaldist"
#define AWAR_DTREE_AUTO_JUMP "awt/dtree/autojump"
#define AWAR_DTREE_SHOW_CIRCLE "awt/dtree/show_circle"
#define AWAR_DTREE_SHOW_BRACKETS "awt/dtree/show_brackets"
#define AWAR_DTREE_CIRCLE_ZOOM "awt/dtree/circle_zoom"
#define AWAR_DTREE_CIRCLE_MAX_SIZE "awt/dtree/max_size"
#define AWAR_DTREE_USE_ELLIPSE "awt/dtree/ellipse"
#define AWAR_DTREE_GREY_LEVEL "awt/dtree/greylevel"
#define AWAR_DTREE_RADIAL_ZOOM_TEXT "awt/dtree/radial/zoomtext"
#define AWAR_DTREE_RADIAL_XPAD "awt/dtree/radial/xpadding"
#define AWAR_DTREE_DENDRO_ZOOM_TEXT "awt/dtree/dendro/zoomtext"
#define AWAR_DTREE_DENDRO_XPAD "awt/dtree/dendro/xpadding"
void awt_create_dtree_awars(AW_root *aw_root, AW_default db);
#define NT_BOX_WIDTH 7 // pixel
#define NT_ROOT_WIDTH 9
#define NT_SELECTED_WIDTH 11
#define AWT_TREE(ntw) DOWNCAST(AWT_graphic_tree*, (ntw)->gfx)
enum AP_tree_display_type {
AP_TREE_NORMAL, // normal tree display (dendrogram)
AP_TREE_RADIAL, // radial tree display
AP_TREE_IRS, // like AP_TREE_NORMAL, with folding line
AP_LIST_NDS,
AP_LIST_SIMPLE // simple display only showing name (used at startup to avoid NDS error messages)
};
enum AP_tree_jump_type { // bit-values
AP_JUMP_UNFOLD_GROUPS = 1,
AP_JUMP_CENTER_IF_VISIBLE = 2, // if already visible -> center (normally only done if IRS-mode or selected was invisible)
AP_JUMP_BE_VERBOOSE = 4, // tell why nothing happened etc.
// convenience defs:
AP_JUMP_AUTO = 0,
AP_JUMP_BY_BUTTON = AP_JUMP_UNFOLD_GROUPS|AP_JUMP_CENTER_IF_VISIBLE|AP_JUMP_BE_VERBOOSE,
};
inline bool sort_is_list_style(AP_tree_display_type sort) { return sort == AP_LIST_NDS || sort == AP_LIST_SIMPLE; }
inline bool sort_is_tree_style(AP_tree_display_type sort) { return !sort_is_list_style(sort); }
class AWT_graphic_tree_group_state;
struct AWT_scaled_font_limits {
double ascent;
double descent;
double height;
double width;
void init(const AW_font_limits& font_limits, double factor) {
ascent = font_limits.ascent*factor;
descent = font_limits.descent*factor;
height = font_limits.height*factor;
width = font_limits.width*factor;
}
};
enum AD_MAP_VIEWER_TYPE {
ADMVT_NONE = 0,
ADMVT_INFO,
ADMVT_WWW,
ADMVT_SELECT
};
typedef void (*AD_map_viewer_cb)(GBDATA *gbd, AD_MAP_VIEWER_TYPE type);
struct DendroSubtreeLimits {
double y_branch; // ypos of branch to subtree
double y_top; // top ypos of whole subtree
double y_bot; // bottom ypos of whole subtree
double x_right; // rightmost xpos of whole subtree
void combine(const DendroSubtreeLimits& other) {
y_top = std::min(y_top, other.y_top);
y_bot = std::max(y_bot, other.y_bot);
x_right = std::max(x_right, other.x_right);
}
};
struct AWT_command_data {
/*! any kind of data which has to be stored between different events (e.g. to support drag&drop)
* Purpose of this class is to allow to delete such data w/o knowing anything else.
*/
virtual ~AWT_command_data() {}
};
enum CollapseMode {
COLLAPSE_ALL = 0,
EXPAND_MARKED = 1, // do not collapse groups containing marked species
COLLAPSE_TERMINAL = 2, // do not collapse groups with subgroups
EXPAND_ALL = 4,
EXPAND_COLOR = 8, // do not collapse groups containing species with color == parameter 'color_group'
};
class AWT_graphic_tree : public AWT_graphic, virtual Noncopyable {
char *species_name;
AW::Position cursor;
int baselinewidth;
int show_brackets;
int show_circle;
int use_ellipse;
float circle_zoom_factor;
float circle_max_size;
int zombies; // # of zombies during last load()
int duplicates; // # of duplicates during last load()
AW_pos paint_irs_sub_tree(AP_tree *node, AW_pos x_offset); // returns y pos
void unload();
// variables - tree compatibility
AP_tree * tree_proto;
bool link_to_database; // link on load ?
double list_tree_ruler_y;
double irs_tree_ruler_scale_factor;
AWT_scaled_font_limits scaled_font;
double scaled_branch_distance; // vertical distance between branches (may be extra-scaled in options)
AW_pos grey_level;
AW_device *disp_device; // device for recursive functions
const AW_bitset line_filter, vert_line_filter, mark_filter, group_bracket_filter, bs_circle_filter;
const AW_bitset leaf_text_filter, group_text_filter, remark_text_filter, other_text_filter;
const AW_bitset ruler_filter, root_filter;
bool nds_show_all;
AD_map_viewer_cb map_viewer_cb;
AWT_command_data *cmd_data;
void scale_text_koordinaten(AW_device *device, int gc, double& x, double& y, double orientation, int flag);
// functions to compute displayinformation
void show_dendrogram(AP_tree *at, AW::Position& pen, DendroSubtreeLimits& limits);
void show_radial_tree(AP_tree *at,
double x_center,
double y_center,
double tree_sprad,
double tree_orientation,
double x_root,
double y_root);
void show_nds_list(GBDATA * gb_main, bool use_nds);
void show_irs_tree(AP_tree *at, double height);
void box(int gc, const AW::Position& pos, int pixel_width, bool filled);
void filled_box(int gc, const AW::Position& pos, int pixel_width) { box(gc, pos, pixel_width, true); }
void empty_box(int gc, const AW::Position& pos, int pixel_width) { box(gc, pos, pixel_width, false); }
void diamond(int gc, const AW::Position& pos, int pixel_width);
const char *ruler_awar(const char *name);
void set_line_attributes_for(AP_tree *at) const {
disp_device->set_line_attributes(at->gr.gc, at->get_linewidth()+baselinewidth, AW_SOLID);
}
virtual void read_tree_settings();
void update_structure() {
AP_tree *root = get_root_node();
if (root) root->compute_tree();
}
void apply_zoom_settings_for_treetype(AWT_canvas *ntw);
int draw_branch_line(int gc, const AW::Position& root, const AW::Position& leaf, AW_bitset filter) {
const AW_click_cd *old = disp_device->get_click_cd();
td_assert(old && old->get_cd1() && !old->get_cd2()); // cd1 should be the node
AW_click_cd branch(disp_device, old->get_cd1(), (AW_CL)"branch");
return disp_device->line(gc, root, leaf, filter);
}
bool warn_inappropriate_mode(AWT_COMMAND_MODE mode);
protected:
void store_command_data(AWT_command_data *new_cmd_data) {
delete cmd_data;
cmd_data = new_cmd_data;
}
AWT_command_data *get_command_data() { return cmd_data; }
public:
// *********** read only variables !!!
AW_root *aw_root;
AP_tree_display_type tree_sort;
AP_tree *displayed_root; // root node of shown (sub-)tree; differs from real root if tree is zoomed logically
AP_tree_root *tree_static;
GBDATA *gb_main;
// *********** public section
AWT_graphic_tree(AW_root *aw_root, GBDATA *gb_main, AD_map_viewer_cb map_viewer_cb);
~AWT_graphic_tree() OVERRIDE;
AP_tree *get_root_node() { return tree_static ? tree_static->get_root_node() : NULL; }
bool is_logically_zoomed() { return displayed_root != get_root_node(); }
void init(RootedTreeNodeFactory *nodeMaker_, AliView *aliview, AP_sequence *seq_prototype, bool link_to_database_, bool insert_delete_cbs);
AW_gc_manager init_devices(AW_window *, AW_device *, AWT_canvas *ntw) OVERRIDE;
void show(AW_device *device) OVERRIDE;
const AW::Position& get_cursor() const { return cursor; }
void info(AW_device *device, AW_pos x, AW_pos y, AW_clicked_line *cl, AW_clicked_text *ct) OVERRIDE;
private:
void handle_key(AW_device *device, AWT_graphic_event& event);
public:
void handle_command(AW_device *device, AWT_graphic_event& event) OVERRIDE;
void mark_species_in_tree(AP_tree *at, int mark);
void mark_species_in_tree_that(AP_tree *at, int mark, int (*condition)(GBDATA*, void*), void *cd);
void mark_species_in_rest_of_tree(AP_tree *at, int mark);
void mark_species_in_rest_of_tree_that(AP_tree *at, int mark, int (*condition)(GBDATA*, void*), void *cd);
bool tree_has_marks(AP_tree *at);
bool rest_tree_has_marks(AP_tree *at);
void detect_group_state(AP_tree *at, AWT_graphic_tree_group_state *state, AP_tree *skip_this_son);
bool group_tree(AP_tree *at, CollapseMode mode, int color_group);
void group_rest_tree(AP_tree *at, CollapseMode mode, int color_group);
void reorder_tree(TreeOrder mode);
GB_ERROR create_group(AP_tree * at) __ATTR__USERESULT;
void toggle_group(AP_tree * at);
GB_ERROR load(GBDATA *gb_main, const char *name, AW_CL, AW_CL) OVERRIDE __ATTR__USERESULT;
GB_ERROR save(GBDATA *gb_main, const char *name, AW_CL cd1, AW_CL cd2) OVERRIDE __ATTR__USERESULT;
int check_update(GBDATA *gb_main) OVERRIDE; // reload tree if needed
void update(GBDATA *gb_main) OVERRIDE;
void set_tree_type(AP_tree_display_type type, AWT_canvas *ntw);
double get_irs_tree_ruler_scale_factor() const { return irs_tree_ruler_scale_factor; }
void show_ruler(AW_device *device, int gc);
void get_zombies_and_duplicates(int& zomb, int& dups) const { zomb = zombies; dups = duplicates; }
#if defined(UNIT_TESTS) // UT_DIFF
friend class fake_AWT_graphic_tree;
#endif
};
class ClickedTarget {
/*! Represents any target corresponding to some (mouse-)position in the tree display.
*
* The target is e.g. used as target for keystrokes or mouse clicks.
*
* For AP_LIST_NDS, this only represents the species (w/o any tree information).
* For other tree display modes, this represents a specific tree node.
*
* The space outside the tree does represent the whole tree (aka the root-node).
* (the necessary distance to the tree-structure/-text is defined by AWT_CATCH)
*/
AP_tree *tree_node;
GBDATA *gb_species;
bool ruler;
bool branch;
const AW_clicked_element *elem;
void init() {
tree_node = NULL;
gb_species = NULL;
ruler = false;
branch = false;
}
void identify(AWT_graphic_tree *agt) {
init();
if (elem && elem->exists) {
const char *what = (const char*)elem->cd2();
if (what) {
if (strcmp(what, "species") == 0) { // entry in NDS list
gb_species = (GBDATA*)elem->cd1();
td_assert(gb_species);
}
else if (strcmp(what, "ruler") == 0) {
ruler = !elem->cd1();
}
else if (strcmp(what, "branch") == 0) {
branch = true; // indicates that a line really IS the branch (opposed to other branch-related lines like e.g. group-brackets)
}
else {
td_assert(0); // unknown element type
}
}
if (!(gb_species || ruler)) {
tree_node = (AP_tree*)elem->cd1();
td_assert(branch || !what);
}
}
else { // use whole tree if mouse does not point to a subtree
tree_node = agt ? agt->get_root_node() : NULL;
}
td_assert(implicated(branch, tree_node));
}
public:
ClickedTarget(AWT_graphic_tree *agt, const AW_clicked_element *clicked) : elem(clicked) {
// uses root of tree as target, when a position outside of the tree is selected
// (e.g. used for key-commands)
identify(agt);
}
ClickedTarget(const AW_clicked_element *clicked) : elem(clicked) {
// accept only normal branches as targets
identify(NULL);
}
const AW_clicked_element *element() const { return elem; }
AP_tree *node() const { return tree_node; }
GBDATA *species() const { return gb_species; }
bool is_text() const { return elem && elem->is_text(); }
bool is_line() const { return elem && elem->is_line(); }
bool is_branch() const { return branch; }
bool is_ruler() const { return ruler; }
double get_rel_attach() const {
// return [0..1] according to exact position where element is dropped
if (is_line() && (is_branch() || ruler)) return elem->get_rel_pos();
return 0.5; // act like "drop on branch-center"
}
};
AWT_graphic_tree *NT_generate_tree(AW_root *root, GBDATA *gb_main, AD_map_viewer_cb map_viewer_cb);
bool AWT_show_branch_remark(AW_device *device, const char *remark_branch, bool is_leaf, AW_pos x, AW_pos y, AW_pos alignment, AW_bitset filteri);
#else
#error TreeDisplay.hxx included twice
#endif // TREEDISPLAY_HXX
// =============================================================== //
// //
// File : irstree_display.cxx //
// Purpose : //
// //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// =============================================================== //
#include "TreeDisplay.hxx"
#include <nds.h>
using namespace AW;
// *********************** paint sub tree ************************
const int tipBoxSize = 3;
struct IRS_data {
bool draw_separator;
AW_pos y;
AW_pos min_y; // ypos of folding line
AW_pos max_y;
AW_pos step_y;
AW_pos halfstep_y;
AW_pos onePixel;
AW_pos fold_x1, fold_x2;
int group_closed;
double x_scale;
Vector adjust_text;
AW_pos tree_depth;
AW_pos gap; // between group frame and (box or text)
AW_pos openGroupExtra; // extra y-size of unfolded groups
AW_bitset sep_filter;
bool is_size_device;
void draw_top_separator_once(AW_device *device) {
if (draw_separator) {
if (!is_size_device) {
device->set_line_attributes(AWT_GC_GROUPS, 4, AW_SOLID);
device->line(AWT_GC_GROUPS, fold_x1, min_y, fold_x2, min_y, sep_filter);
}
draw_separator = false;
}
}
};
static IRS_data IRS;
AW_pos AWT_graphic_tree::paint_irs_sub_tree(AP_tree *node, AW_pos x_offset) {
if (!IRS.is_size_device) {
// check clipping rectangle
if (IRS.y > IRS.max_y) {
return IRS.max_y;
}
AW_pos height_of_subtree = IRS.step_y*node->gr.view_sum;
if (IRS.y + height_of_subtree < IRS.min_y) {
IRS.y += height_of_subtree;
return IRS.min_y;
}
}
if (node->is_leaf) {
IRS.y+=IRS.step_y;
IRS.draw_top_separator_once(disp_device);
Position leaf(x_offset, IRS.y);
if (node->hasName(species_name)) {
cursor = leaf;
if (IRS.is_size_device) {
// hack to fix calculated cursor position:
// - IRS tree reports different cursor positions in AW_SIZE and normal draw modes.
// - the main reason for the difference is the number of open groups clipped away
// above the separator line.
// - There is still some unhandled difference mostlikely caused by the number of
// open groups on the screen, but in most cases the cursor position is inside view now.
double correctionPerGroup = IRS.openGroupExtra; // depends on size of marked-species-font
double cursorCorrection = -IRS.group_closed * correctionPerGroup;
cursor.movey(cursorCorrection);
}
}
AW_click_cd cd(disp_device, (AW_CL)node);
int gc = node->gr.gc;
if (node->gb_node && GB_read_flag(node->gb_node)) {
set_line_attributes_for(node);
filled_box(gc, leaf, NT_BOX_WIDTH);
}
Position textpos = leaf+IRS.adjust_text;
const char *specinfo = make_node_text_nds(gb_main, node->gb_node, NDS_OUTPUT_LEAFTEXT, node, tree_static->get_tree_name());
disp_device->text(gc, specinfo, textpos);
return IRS.y;
}
const char *group_name = NULL;
AW_pos frame_width = -1;
if (node->gb_node) {
if (!node->father) { // root node - don't try to get taxonomy
group_name = tree_static->get_tree_name();
}
else {
group_name = make_node_text_nds(gb_main, node->gb_node, NDS_OUTPUT_LEAFTEXT, node, tree_static->get_tree_name());
}
frame_width = node->gr.max_tree_depth * IRS.x_scale;
}
if (node->gr.grouped) { // folded group
AW_pos y_center;
AW_pos frame_height = node->gr.view_sum * IRS.step_y;
AW_pos frame_y1 = IRS.y+IRS.halfstep_y+IRS.gap;
AW_pos frame_y2 = frame_y1 + frame_height;
if (frame_y2 >= IRS.min_y) {
if (frame_y1 < IRS.min_y) { // shift folded groups into the folding area (disappears when completely inside)
frame_y1 = IRS.min_y;
IRS.min_y += IRS.halfstep_y+IRS.gap;
}
AW_pos visible_frame_height = frame_y2-frame_y1;
Rectangle frame(Position(x_offset, frame_y1), Vector(frame_width, visible_frame_height));
// draw group frame (unclosed on right hand):
AW_click_cd cd(disp_device, (AW_CL)node);
int gc = AWT_GC_GROUPS;
disp_device->set_line_attributes(gc, 1, AW_SOLID);
disp_device->line(gc, frame.upper_edge());
disp_device->line(gc, frame.left_edge());
disp_device->line(gc, frame.lower_edge());
gc = node->gr.gc;
disp_device->set_grey_level(gc, grey_level);
set_line_attributes_for(node);
filled_box(gc, frame.upper_left_corner(), tipBoxSize);
Vector frame2box(IRS.gap, IRS.gap);
Rectangle gbox(frame.upper_left_corner()+frame2box, Vector(frame.width()*.5, frame.height()-2*IRS.gap));
disp_device->box(gc, true, gbox);
Position box_rcenter = gbox.right_edge().centroid();
if (group_name) { // a node name should be displayed
const char *groupinfo = GBS_global_string("%s (%u)", group_name, node->gr.leaf_sum);
disp_device->text(gc, groupinfo, box_rcenter+IRS.adjust_text);
}
IRS.draw_top_separator_once(disp_device);
IRS.y += frame_height + 2*IRS.gap;
y_center = box_rcenter.ypos();
}
else {
IRS.y += frame_height + 2*IRS.gap;
y_center = IRS.min_y;
if (IRS.y > IRS.min_y) {
IRS.y = IRS.min_y;
}
}
return y_center;
}
AW_pos group_y1 = IRS.y;
if (group_name != NULL) { // unfolded group
if (group_y1 >= IRS.min_y) {
IRS.draw_top_separator_once(disp_device);
group_y1 = IRS.y + IRS.halfstep_y+IRS.gap;
}
else {
group_y1 = IRS.min_y;
IRS.min_y += IRS.openGroupExtra;
}
IRS.y += IRS.openGroupExtra;
int gc = AWT_GC_GROUPS;
AW_click_cd cd(disp_device, (AW_CL)node);
disp_device->set_line_attributes(gc, 1, AW_DOTTED);
disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset+frame_width, group_y1); // opened-group-frame
const char *groupinfo = GBS_global_string("%s (%u)", group_name, node->gr.leaf_sum);
disp_device->text(node->gr.gc, groupinfo, x_offset-IRS.onePixel + IRS.gap, group_y1 + 2*IRS.adjust_text.y() + IRS.gap);
}
// draw subtrees
AW_pos left_x = x_offset + IRS.x_scale * node->leftlen;
AW_pos left_y = paint_irs_sub_tree(node->get_leftson(), left_x);
AW_pos right_x = x_offset + IRS.x_scale * node->rightlen;
AW_pos right_y = paint_irs_sub_tree(node->get_rightson(), right_x);
if (group_name != NULL) IRS.group_closed++;
// draw structure
if (left_y > IRS.min_y) {
if (left_y < IRS.max_y) { // clip y on top border
AW_click_cd cd(disp_device, (AW_CL)node->leftson);
if (node->leftson->get_remark()) {
AWT_show_branch_remark(disp_device, node->leftson->get_remark(), node->leftson->is_leaf, left_x, left_y, 1, remark_text_filter);
}
set_line_attributes_for(node->get_leftson());
draw_branch_line(node->get_leftson()->gr.gc, Position(x_offset, left_y), Position(left_x, left_y), line_filter);
}
}
else {
left_y = IRS.min_y;
}
AW_pos y_center = (left_y + right_y)*0.5;
if (right_y > IRS.min_y && right_y < IRS.max_y) { // visible right branch in lower part of display
AW_click_cd cd(disp_device, (AW_CL)node->rightson);
if (node->rightson->get_remark()) {
AWT_show_branch_remark(disp_device, node->rightson->get_remark(), node->rightson->is_leaf, right_x, right_y, 1, remark_text_filter);
}
set_line_attributes_for(node->get_rightson());
draw_branch_line(node->get_rightson()->gr.gc, Position(x_offset, right_y), Position(right_x, right_y), line_filter);
}
AW_click_cd cd(disp_device, (AW_CL)node);
set_line_attributes_for(node->get_leftson());
disp_device->line(node->get_leftson()->gr.gc, x_offset, y_center, x_offset, left_y);
set_line_attributes_for(node->get_rightson());
disp_device->line(node->get_rightson()->gr.gc, x_offset, y_center, x_offset, right_y);
if (group_name != NULL) { // close unfolded group brackets and draw tipbox
IRS.y += IRS.halfstep_y+IRS.gap;
int gc = AWT_GC_GROUPS;
disp_device->set_line_attributes(gc, 1, AW_DOTTED);
disp_device->line(gc, x_offset-IRS.onePixel, IRS.y, x_offset+frame_width, IRS.y); // opened-group-frame
disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset-IRS.onePixel, IRS.y); // opened-group-frame
gc = node->gr.gc;
disp_device->set_grey_level(gc, grey_level);
set_line_attributes_for(node);
filled_box(gc, Position(x_offset-IRS.onePixel, group_y1), tipBoxSize);
}
return y_center;
}
void AWT_graphic_tree::show_irs_tree(AP_tree *at, double height) {
IRS.draw_separator = true;
IRS.y = 0;
IRS.step_y = height;
IRS.halfstep_y = IRS.step_y*0.5;
IRS.x_scale = 200.0; // @@@ should not have any effect, since display gets x-scaled. But if it's to low (e.g. 1.0) scaling on zoom-reset does not work
const AW_font_limits& limits = disp_device->get_font_limits(AWT_GC_SELECTED, 0);
IRS.adjust_text = disp_device->rtransform(Vector(NT_BOX_WIDTH, limits.ascent*0.5));
IRS.onePixel = disp_device->rtransform_size(1.0);
IRS.gap = 3*IRS.onePixel;
IRS.group_closed = 0;
IRS.tree_depth = at->gr.max_tree_depth;
IRS.openGroupExtra = IRS.step_y+IRS.gap;
IRS.sep_filter = AW_SCREEN|AW_PRINTER_CLIP;
IRS.is_size_device = disp_device->type() == AW_DEVICE_SIZE;
Position corner = disp_device->rtransform(Origin); // real world coordinates of left/upper screen corner
Rectangle rclip = disp_device->get_rtransformed_cliprect();
// the following values currently contain nonsense for size device @@@
IRS.min_y = corner.ypos();
IRS.max_y = rclip.bottom();
IRS.fold_x1 = rclip.left();
IRS.fold_x2 = rclip.right();
list_tree_ruler_y = paint_irs_sub_tree(at, 0);
irs_tree_ruler_scale_factor = IRS.x_scale;
disp_device->invisible(corner); // @@@ remove when size-dev works
}
# libraries needed to link against SL/TREEDISP/TREEDISP.a
SL/AP_TREE/AP_TREE.a
SL/NDS/NDS.a
# for variables passed from parent makefile see ../../SOURCE_TOOLS/parent_make.txt
.SUFFIXES: .o .cxx .depend
OBJECTS=$(subst .cxx,.o,$(wildcard *.cxx))
$(MAIN): $(OBJECTS)
$(LINK_STATIC_LIB) $(MAIN) $(OBJECTS)
.cxx.o:
$(A_CXX) $(cflags) $(cxxflags) -c $< $(CXX_INCLUDES) $(POST_COMPILE)
clean:
rm -f $(OBJECTS) *.a
DEPENDS = $(OBJECTS:.o=.depend)
depends: $(DEPENDS)
@cat $(DEPENDS) | grep -v '^#' >>Makefile
@rm $(DEPENDS)
$(DEPENDS): depend.init
depend.init:
$(MAKEDEPEND) $(MAKEDEPENDFLAGS) 2>/dev/null # remove dependencies
.c.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
.cxx.depend:
$(MAKEDEPEND) -f- $(MAKEDEPENDFLAGS) $< 2>/dev/null >$@
# DO NOT DELETE
# Do not add dependencies manually - use 'make depend' in $ARBHOME
# For formatting issues see SOURCE_TOOLS/fix_depends.pl (from SL)
TreeAdmin.o: TreeAdmin.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/ad_prot.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/ad_t_prot.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_assert.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_core.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_error.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_global_defs.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_msg.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_strbuf.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arb_string.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arbdb.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arbdb_base.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arbdbt.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/arbtools.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/attributes.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_awar.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_base.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_keysym.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_msg.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_root.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/aw_window.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/awt_TreeAwars.hxx
TreeAdmin.o: $(ARBHOME)/INCLUDE/cb.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/cb_base.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/cbtypes.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/cxxforward.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/downcast.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/dupstr.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/gccver.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/smartptr.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/static_assert.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/test_global.h
TreeAdmin.o: $(ARBHOME)/INCLUDE/ttypes.h
// ============================================================= //
// //
// File : TreeAdmin.cxx //
// Purpose : Common tree admin functionality //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in April 2012 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ============================================================= //
#include "TreeAdmin.h"
#include <aw_window.hxx>
#include <aw_root.hxx>
#include <aw_awar.hxx>
#include <arbdbt.h>
#include <arb_strbuf.h>
#include <cctype>
#include <aw_msg.hxx>
#include <arb_global_defs.h>
#include <awt_TreeAwars.hxx>
#define ta_assert(cond) arb_assert(cond)
#define AWAR_TREE_SOURCE "tmp/ad_tree/tree_source"
#define AWAR_TREE_DEST "tmp/ad_tree/tree_dest"
namespace TreeAdmin {
void create_awars(AW_root *root, AW_default aw_def, bool registerTreeAwar) {
AW_awar *awar_srcTree = root->awar_string(AWAR_TREE_SOURCE, 0, aw_def)->set_srt(GBT_TREE_AWAR_SRT);
if (registerTreeAwar) AWT_registerTreeAwarSimple(awar_srcTree);
root->awar_string(AWAR_TREE_DEST, 0, aw_def)->set_srt(GBT_TREE_AWAR_SRT); // no need to register (awar always follows the tree selected in admin window!)
}
AW_awar *source_tree_awar(AW_root *root) {
return root->awar(AWAR_TREE_SOURCE);
}
AW_awar *dest_tree_awar(AW_root *root) {
return root->awar(AWAR_TREE_DEST);
}
AW_awar *Spec::tree_awar(AW_root *awr) const {
return awr->awar(awar_selected_tree);
}
void delete_tree_cb(AW_window *aww, const Spec *spec) {
AW_awar *awar_tree = spec->tree_awar(aww->get_root());
char *name = awar_tree->read_string();
GBDATA *gb_main = spec->get_gb_main();
GB_ERROR error = NULL;
GBDATA *gb_tree;
// 1. TA: switch to next tree
{
GB_transaction ta(gb_main);
gb_tree = GBT_find_tree(gb_main, name);
if (!gb_tree) error = "Please select tree to delete";
else {
AWT_announce_tree_deleted(name);
GBDATA *gb_next = GBT_find_next_tree(gb_tree);
awar_tree->write_string(gb_next ? GBT_get_tree_name(gb_next) : NO_TREE_SELECTED);
}
error = ta.close(error);
}
// 2. TA: delete old tree
if (!error) {
GB_transaction ta(gb_main);
error = GB_delete(gb_tree);
error = ta.close(error);
}
if (error) {
aw_message(error);
awar_tree->write_string(name); // switch back to failed tree
}
free(name);
}
static GB_ERROR tree_append_remark(GBDATA *gb_tree, const char *add_to_remark) {
GB_ERROR error = 0;
GBDATA *gb_remark = GB_search(gb_tree, "remark", GB_STRING);
if (!gb_remark) error = GB_await_error();
else {
char *old_remark = GB_read_string(gb_remark);
if (!old_remark) error = GB_await_error();
else {
GBS_strstruct *new_remark = GBS_stropen(2000);
GBS_strcat(new_remark, old_remark);
GBS_chrcat(new_remark, '\n');
GBS_strcat(new_remark, add_to_remark);
error = GB_write_string(gb_remark, GBS_mempntr(new_remark));
GBS_strforget(new_remark);
}
free(old_remark);
}
return error;
}
static void tree_copy_or_rename_cb(AW_window *aww, bool do_copy, const Spec& spec) {
AW_root *aw_root = aww->get_root();
AW_awar *awar_tree = spec.tree_awar(aw_root);
char *source = awar_tree->read_string();
char *dest = aw_root->awar(AWAR_TREE_DEST)->read_string();
GB_ERROR error = NULL;
if (!error && !dest[0]) error = "Please enter new tree name";
if (!error) {
GBDATA *gb_main = spec.get_gb_main();
error = GB_begin_transaction(gb_main);
if (!error) {
if (do_copy) {
error = GBT_copy_tree(gb_main, source, dest);
if (!error) {
GBDATA *gb_new_tree = GBT_find_tree(gb_main, dest);
ta_assert(gb_new_tree);
error = tree_append_remark(gb_new_tree, GBS_global_string("[created as copy of '%s']", source));
}
}
else {
error = GBT_rename_tree(gb_main, source, dest);
if (!error) AWT_announce_tree_renamed(source, dest);
}
}
if (!error) awar_tree->write_string(dest);
error = GB_end_transaction(gb_main, error);
}
aww->hide_or_notify(error);
free(dest);
free(source);
}
static void tree_rename_cb(AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, false, *spec); }
static void tree_copy_cb (AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, true, *spec); }
static void current_as_dest_treename_cb(AW_window *aww, const Spec *spec) {
AW_root *awr = aww->get_root();
dest_tree_awar(awr)->write_string(spec->tree_awar(awr)->read_char_pntr());
}
static void make_dest_treename_unique_cb(AW_window *aww, const Spec *spec) {
// generated a unique treename
AW_root *awr = aww->get_root();
AW_awar *awar_dest = awr->awar(AWAR_TREE_DEST);
char *name = awar_dest->read_string();
int len = strlen(name);
for (int p = len-1; p >= 0; --p) {
bool auto_modified = isdigit(name[p]) || name[p] == '_';
if (!auto_modified) break;
name[p] = 0;
}
{
GBDATA *gb_main = spec->get_gb_main();
GB_transaction ta(gb_main);
if (!GBT_find_tree(gb_main, name)) {
awar_dest->write_string("");
awar_dest->write_string(name);
}
else {
for (int i = 2; ; i++) {
const char *testName = GBS_global_string("%s_%i", name, i);
if (!GBT_find_tree(gb_main, testName)) { // found unique name
awar_dest->write_string(testName);
break;
}
}
}
}
free(name);
}
static AW_window *create_copy_or_rename_window(AW_root *root, const char *win_id, const char *win_title, const char *go_label, void (*go_cb)(AW_window*, const Spec*), const Spec *spec) {
AW_window_simple *aws = new AW_window_simple;
aws->init(root, win_id, win_title);
aws->at(10, 10);
aws->auto_space(10, 10);
aws->at_newline();
aws->label("Current:");
aws->callback(makeWindowCallback(current_as_dest_treename_cb, spec));
aws->at_set_to(true, false, -10, 25);
aws->create_button("use_current", spec->tree_awar(aws->get_root())->awar_name);
aws->at_newline();
aws->label("New: ");
aws->at_set_to(true, false, -10, 30);
aws->create_input_field(AWAR_TREE_DEST);
aws->at_newline();
aws->callback(makeWindowCallback(go_cb, spec));
aws->create_autosize_button("GO", go_label, "");
aws->callback((AW_CB0)AW_POPDOWN);
aws->create_autosize_button("CLOSE", "Abort", "A");
aws->callback(makeWindowCallback(make_dest_treename_unique_cb, spec));
aws->create_autosize_button("UNIQUE", "Unique name", "U");
aws->at_newline();
return aws;
}
AW_window *create_rename_window(AW_root *root, const Spec *spec) {
return create_copy_or_rename_window(root, "RENAME_TREE", "Rename Tree", "Rename Tree", tree_rename_cb, spec);
}
AW_window *create_copy_window(AW_root *root, const Spec *spec) {
return create_copy_or_rename_window(root, "COPY_TREE", "Copy Tree", "Copy Tree", tree_copy_cb, spec);
}
};
// ============================================================= //
// //
// File : TreeAdmin.h //
// Purpose : Common tree admin functionality //
// //
// Coded by Ralf Westram (coder@reallysoft.de) in April 2012 //
// Institute of Microbiology (Technical University Munich) //
// http://www.arb-home.de/ //
// //
// ============================================================= //
#ifndef TREEADMIN_H
#define TREEADMIN_H
#ifndef AW_BASE_HXX
#include <aw_base.hxx>
#endif
class AW_awar;
namespace TreeAdmin {
class Spec {
GBDATA *gb_main;
const char *awar_selected_tree;
public:
Spec(GBDATA *gb_main_, const char *awar_selected_tree_)
: gb_main(gb_main_),
awar_selected_tree(awar_selected_tree_)
{}
GBDATA *get_gb_main() const { return gb_main; }
AW_awar *tree_awar(AW_root *awr) const;
};
void create_awars(AW_root *root, AW_default aw_def, bool registerTreeAwar);
AW_awar *dest_tree_awar(AW_root *root);
AW_awar *source_tree_awar(AW_root *root);
AW_window *create_rename_window(AW_root *root, const Spec *spec);
AW_window *create_copy_window(AW_root *root, const Spec *spec);
void delete_tree_cb(AW_window *aww, const Spec *spec);
};
#else
#error TreeAdmin.h included twice
#endif // TREEADMIN_H