/*\
* Autocad ADS library C++ link
* $Id: adsapp.cpp 1.1 1994/11/09 11:24:06 leon Exp leon $
\*/
// #define ADSDEBUG
#include <algo.h> // stl
#include "adsapp.hpp"
#include <string.h>
ADSFunction::ADSFunction(void (*pFunc)(), const char *name, short number)
: name(name), number(number), pFunc(pFunc){}
/**
** Na zahtevo sistema nalozi funkcije, ki smo jih registrirali s
** funkcijo Register. Funkcija je vitrualna in jo lahko uporabimo
** za zagon svojih funkcij, ki naj bi se izvedle ob zagonu z ukazom
** (xload "file.exp")
**/
short ADSApplication::load()
{
for (short i = 0; i < total; i++)
fArray[i].load();
return RTNORM;
};
/**
** Podobno kot funkcija load() se ta izvede, ko sistem zahteva
** brisanje aplikacije iz spomina. Funkcije se brisejo. Uporabnik
** pa lahko prepise (overloada) funkcijo s svojo, da pobrise za sabo
** vsa globalna polja, neshranjene podatke in podobno.
**/
short ADSApplication::unload()
{
for (short i = 0; i < total; i++)
fArray[i].unload();
return RTNORM;
};
/**
** Ko sistem AutoCad dobi ustrezen ukaz od Lisp-a se ugotovi, katera
** funkcija je to bila in jo izvrsi.
**/
short ADSApplication::execute()
{
int val;
if ((val = ads_getfuncode ()) < 0)
return 0;
fArray[val].execute();
return RTNORM;
}
/**
** Registrira funkcijo /func/ z imenom /funcName/ katerega lahko
** odtipkamo v ukazni vrstici.
**/
void ADSApplication::Register(void (*func)(), const char *funcName)
{
fArray.push_back(ADSFunction(func, funcName, total++));
}
/**
** Registrira aplikacijo z imenom /appName/, da jo lahko uporabimo
** pri graditvi XDATA.
**/
void ADSApplication::Register(const char *appName)
{
struct resbuf *rb;
if ((rb = ads_tblsearch("APPID", appName, 0)) == NULL)
{
if (ads_regapp(appName) != RTNORM)
ads_printf("Can't register XDATA for %s.\n", appName);
}
else
ads_relrb(rb);
}
/**
** Glavna funkcija za zagon aplikacije, ki vsebuje zanko za
** komunikacijo z AutoLispom. Argumenti /argc/ in /argv/ so
** isti kot pri funkciji main(int argc, char *argv[])
**/
void ADSApplication::Run(int argc, char *argv[])
{
int scode = RSRSLT; // Normal result code (default)
int stat;
ads_init (argc, argv); // Initiate communication with AutoLISP
for (;;)
{ /* Request/Result loop */
if ((stat = ads_link (scode)) < 0)
{
cout << "Error: %d\n", stat;
cout.flush();
exit (1);
}
scode = RSRSLT; // Reset result code
switch (stat)
{
case RQXLOAD: // Load & define functions
scode = load () ? -RSRSLT : -RSERR;
initialize();
break;
case RQXUNLD: // Unload functions
scode = unload () ? -RSRSLT : -RSERR;
break;
case RQSUBR: // Handle request for external function
scode = execute () ? RSRSLT : RSERR;
break;
default:
break;
}
}
}
static bool operator == (Control const *x, Control const &y)
{
return (*x).key == y.key;
}
void dispatch(ads_callback_packet *cbpkt)
{
char value[50];
ads_get_attr_string(cbpkt->tile, "key", value, 50);
const Control c(value);
set <Control *, less<Control *> >::iterator i =
find(Dialog::current->controls.begin(),
Dialog::current->controls.end(), Control(value));
Dialog::current->HandleMsg((*i)->cmdId, cbpkt);
}
Control::Control (const char *key, int cmdId,
CLIENTFUNC callback)
{
Control::callback = callback;
Control::key = key;
Control::cmdId = cmdId;
}
//////////////////////////////////////////////////////////////////////////
ListBox::ListBox(const ListBox& listbox)
{
copy(listbox.items.begin(), listbox.items.end(), items.begin() );
}
/**
**Doda string /data/ na konec seznama za prikaz
**/
void ListBox::add(const char *data)
{
items.push_back(Item(data));
}
/**
** Zbrise obstoje"ci seznam in pripravi potrebno za novega
**/
void ListBox::newList()
{
items.erase(items.begin(), items.end());
}
/**
** Zahteva izris seznama v dialog oknu
**/
void ListBox::paint(ads_hdlg hdlg)
{
ads_start_list(hdlg, (char *)(const char *)key, LIST_NEW, 0);
// items.forAll(paintItem, hdlg);
for_each(items.begin(), items.end(), Item::paint);
ads_printf("lb paint");
ads_end_list();
}
/**
** Vrne /i/-ti string iz seznama
**/
const char * ListBox::GetString(int i)
{
return (const char *) items[i].item;
}
/**
** Izrise en string v dialog oknu
**/
void Item::paint(Item i)
{
ads_add_list((char *)(const char *)i.item);
}
//////////////////////////////////////////////////////////////////////
/**
** Kreira novo polje za vnos z referenco /key/ in "stevilko sporo"cila
** /cmdId/. /defaultText/ je mo"zno uporabiti za prednastavljeni tekst,
** ki se prika"ze na Dialog oknu.
**/
EditBox::EditBox(const char *key, int cmdId, const char *defaultText)
: Control(key, cmdId)
{
EditBox::defaultText = defaultText;
}
/**
** Izrise tekst v EditBox oknu
**/
void EditBox::paint(ads_hdlg hdlg)
{
ads_set_tile(hdlg, (char *)(const char *)key,
(char *)(const char *)defaultText);
}
/** Nastavi /defaultText/ na tekst /text/ **/
void EditBox::Set(const char *text)
{
defaultText = text;
}
/////////////////////////////////////////////////////////
Dialog *Dialog::current = NULL;
#if 0
/** {secret} **/
void Dialog::addDialogControl(Control * data, void *hdlg)
{
ads_action_tile(*(ads_hdlg *)hdlg,
(char *)(const char *)data->key, data->callback);
}
#endif
/**
** Kreira dialog z imenom /filename/ datoteke .dcl z imenom dialoga
** /dialogKey/ in podrocjem pomoci /topic/.
**/
Dialog::Dialog(const char *filename, const char *dialogKey,
const char *topic)
{
previous = current;
current = this;
file = filename;
Dialog::dialogKey = dialogKey;
if (topic == NULL)
helpTopic = dialogKey;
current = this;
}
/** {duh} **/
Dialog::~Dialog()
{
set <Control *, less<Control *> >::iterator i;
for(i = controls.begin(); i != controls.end(); ++i)
delete *i ;
current = previous;
}
/**
** Podobno kot pri gumbih s to funkcijo tu prestrezamo sporo"cila
** za sezname (ListBox). /cmdId/ je "stevilka seznama, /cbpkt/ pa
** stuktura z informacijo o vrstici in na"cinu izbora, kot je to
** v normalnih /ADS callback/ funkcijah.
**/
void Dialog::HandleMsg(int cmdId, ads_callback_packet *cbpkt)
{
#ifdef ADSDEBUG
ads_printf("ListBox with id: %d was selected with reason %d.\n",
cmdId, cbpkt->reason);
#endif
cmdId = 0;
cbpkt = NULL;
}
/**
** Glavna funkcija za zagon Dialog okna, v kateri je zanka za prestrezanje
** in dispe"ciranje sporo"cil.
**/
void Dialog::Run()
{
ads_load_dialog((char *)(const char *)file, &dlgId);
if (dlgId < 0)
{
ads_fail("Napaka pri odpiranju dialoga");
return;
}
ads_new_dialog ((char *)(const char *)dialogKey, dlgId, NULLCB, &hdlg);
if (hdlg == NULL)
{
ads_fail ("ads_new_dialog funkcija ni uspela");
ads_unload_dialog (dlgId);
return;
}
// add dialog controls
set <Control *, less <Control *> >::iterator i;
for(i = controls.begin(); i != controls.end(); ++i)
{
(*i)->paint(hdlg);
(*i)->addTile(hdlg);
}
StartHook();
status = DLGSTATUS;
while (status >= DLGSTATUS)
{
ads_start_dialog (hdlg, &status);
switch (status)
{
case DLGOK:
Ok();
break;
case DLGCANCEL:
case DLGALLDONE:
Cancel();
break;
default:
HandleMsg();
break;
}
}
// ads_unload_dialog(dlgId);
return;
}
#if 0
/**
** S to funkcijo lahko registriramo funkcije kot je to normalno v ADS
** s /CALLB/ na"cinom. /tileFunc/ je ADSCALLBACK funkcija,
** ki se izvr"si ob dogodku /key/ v dialogu.
**/
void Dialog::Register(CLIENTFUNC tileFunc, const char *key)
{
Control *c = new Control(tileFunc, key);
controls.insert(c);
}
/** {duh} **/
void Dialog::insert(ListBox listbox)
{
listboxes.push_back(listbox);
}
/** {duh} **/
void Dialog::insert(EditBox editbox)
{
editboxes.insert(editbox);
}
#endif
/**
** Dodajamo ukaze dialogu in s tem omogo"cimo izvr"sitev sporo"cila.
**/
void Dialog::insert(Control *control)
{
controls.insert(control);
}
syntax highlighted by Code2HTML, v. 0.9.1