// jakitam sobie opis API libgadu
// (c) copyright 2001-2002 by wojtek kaniewski <wojtekka@irc.pl>
//			      robert j. wozny <speedy@ziew.org>

kada sesja jest opisywana przez ,,struct gg_session''. biblioteka moe
w ramach jednego procesu/wtku obsugiwa tyle sesji, na ile pozwol
zasoby. deklarujemy sobie...

	struct gg_session *blah;

nastpnie wypadaoby si poczy. przykad bdzie dotyczy socketw
nieblokujcych, bo w wikszoci aplikacji ciko sobie pozwoli na
zawieszanie programu na czas czenia.

	struct gg_login_params p;

	memset(&p, 0, sizeof(p));
	p.uin = 123456;
	p.password = "haso";
	p.async = 1;
	p.status = GG_STATUS_INVISIBLE;

	if (!(blah = gg_login(&p)))
		my_error();

jeli uda si rozpocz proces czenia, dostajemy wskanik do struktury,
inaczej NULL. wywoanie gg_login() powoduje uruchomienie drugiego procesu w
tle, ktry wywoa gethostbyname() i przez pipe'a zwrci wynik. pniej
poczy si z serwerem, wyle, odbierze, poczy si ze wskazanym adresem
IP, zaloguje si itd. jako e wszystko dziej si w tle, klient musi
sprawdza cay czas podane deskryptory. pole ,,blah->fd'' zawiera
deskryptor, a ,,blah->check'' jest bitmap i zawiera GG_CHECK_READ i/lub
GG_CHECK_WRITE jeli mamy sprawdzi czy przyszy nowe dane i/lub moemy
wysya. jeli co si wydarzy, wywoujemy ,,gg_watch_fd()'', a libgadu
sobie ju sprawdzi, co takiego si zdarzyo:

	while (1) {
		fd_set rd, wr, ex;

		FD_ZERO(&rd);
		FD_ZERO(&wr);
		FD_ZERO(&ex);

		if ((blah->check & GG_CHECK_READ))
			FD_SET(blah->fd, &rd);
		if ((blah->check & GG_CHECK_WRITE))
			FD_SET(blah->fd, &wr);
		FD_SET(blah->fd, &ex);

		if (select(blah->fd + 1, &rd, &wr, &ex, NULL) == -1)
			my_error();

		if (FD_ISSET(blah->fd, &ex))
			my_error();

		if (FD_ISSET(blah->fd, &rd) || FD_ISSET(blah->fd, &wr))
			my_handle_event();
	}

nie ma tutaj obsugi timeoutw itp. jeli komu zaley, niech sobie
sam dopisze. poza tym, jeli program sprawdza te inne deskryptory
jak np. stdin dla klientw konsolowych, dobrze byoby sprawdzi, czy
dana sesja co robi i nie sprawdza ,,blah->fd'' jeli
,,blah->state == GG_STATE_IDLE''. no i od czasu do czasu mona by
dawa zna serwerowi, e co si dzieje za pomoc...

	gg_ping(blah);

ale to ju wymaga implementacji jakich timeoutw i liczenia czasu od
ostatniego pinga. ,,blah->last_pong'' mwi nam, kiedy serwer ostatni
raz odpowiedzia na pakiet ping, a ,,blah->last_event'' mwi, kiedy
dostalimy cokolwiek ostatnio od serwera.

wracajc do obsugi deskryptorw -- jeli klient zauway, e co si
zmienio na podanym sockecie, powinien wywoa ,,gg_watch_fd()'',
ktra wszystkim si zajmie. zwraca ona wskanik do zaalokowanej
struktury opisujcej zdarzenie. po obejrzeniu naley zwolni j za
pomoc ,,gg_free_event()''. w powyszym przykadzie jest wywoywana
funkcja ,,my_handle_event()'', ktra moe wyglda tak:

	struct gg_event *e;
	
	if (!(e = gg_watch_fd(blah)))
		my_error();

	switch (e->type) {
		case GG_EVENT_NONE:
		case GG_EVENT_PONG:
			/* olewamy */
			break;

		case GG_EVENT_CONN_SUCCESS:
			printf("poczono!\n");
			/* tutaj wysyamy userlist za pomoc gg_notify() */
			break;

		case GG_EVENT_CONN_FAILED:
			printf("nie udao si\n");
			/* powd w e->event.failure, stae GG_FAILURE_... */
			break;

		case GG_EVENT_MSG:
			printf("masz wiadomo!\n");
			printf("od: %d\n", e->event.msg.sender);
			printf("tre: %s\n", e->event.msg.message);
			/* e->event.msg.class mwi czy rozmowa czy wiad. */
			/* jeli e->event.msg.sender rwny 0, to mamy */
			/* wiadomo systemow o numerze w msg.class */
			break;

		case GG_EVENT_NOTIFY:
			printf("oto ludzie, ktrzy si pojawili: ");
			/* tutaj sprawdzanie tablicy e->event.notify */
			break;

		case GG_EVENT_STATUS:
			printf("kto %d zmieni stan\n", e->event.status.uin);
			/* nowy stan w e->event.status.status */
			break;

		case GG_EVENT_ACK:
			printf("wiadomo dotara do %d.\n",
				e->event.ack.recipient);
			/* e->event.ack.status mwi czy dotara do klienta */
			/* czy ley na serwerze, stae GG_ACK_... */
			/* e->event.ack.seq to numerek wiadomoci */
			break;
	}

	gg_free_event(e);

przy okazji wiadomo, co oznacza ktry event. cz z nich mona ignorowa,
jeli robi si okrojonego klienta, np. commandline'owego wysyajcego
jedn wiadomo.

po zalogowaniu wypadaoby wysa serwerowi list uytkownikw, ktrzy nas
interesuj. ,,gg_notify()'' przyjmuje za argument tablic zmiennych typu
,,uin_t''. w odpowiedzi dostaniemy GG_EVENT_NOTIFY i tablic struktur
,,struct gg_notify_reply'', jeli kto jest. po szczegy odsyam do
libgadu.c, libgadu.h i rde konsolowego klienta. jeli dodajemy lub
usuwamy kogo w trakcie dziaania, naley skorzysta z ,,gg_add_notify()''
lub ,,gg_remove_notify()''.

eby zmieni stan na zajty lub dostpny, uywamy ,,gg_change_status()''.

wysyanie wiadomoci za pomoc ,,gg_send_message()''. parametr ,,class''
mwi, czy ma sie pojawi w osobnym okienku (GG_CLASS_MSG) czy w okienku
rozmowy (GG_CLASS_CHAT). funkcja zwraca numer sekwencyjny wiadomoci,
ktrego moemy uy do potwierdzenia.

biblioteka libgadu.c wymaga zdefiniowania / albo i nie WORDS_BIGENDIAN.
jest ona definiowana [albo i nie] przez skrypt configure - i jest definiowana
[#define WORDS_BIGENDIAN 1] gdy mamy maszyn bigendianow.

jeeli piszesz co z uyciem glib, moesz wrzuci co takiego:

	#include <glib.h>

	#if G_BYTE_ORDER == G_BIG_ENDIAN 
	#    define WORDS_BIGENDIAN 1
	#endif

nie testowaem, ale powinno dziaa.
jeeli za nie korzystasz z glib, skryptu configure... to bd ostrzeony: 
bez zdefiniowania WORDS_BIGENDIAN na maszynach bigendianowych nie bdzie 
poprawnie pracowa ;>

$Id: api.txt,v 1.7 2002/04/18 22:13:34 wojtekka Exp $
