Como criar extensões do ToonTalkSomente para usuários muito avançados: Os programadores da linguagem C ou Pascal podem definir novas extensões para o ToonTalk. Um usuário do ToonTalk pensa que uma extensão é um lugar distante, impossível de se visitar. Mas um usuário pode obter um pombo que irá "voando" até lá. O pombo pode até mesmo acompanhar outros pombos, que podem retornar com coisas feitas por uma extensão. As extensões podem realizar qualquer recurso do sistema operacional básico (por exemplo, o Windows) disponível para os usuários dentro do ToonTalk. Os exemplos incluem arquivos, gerenciamento de janelas, acesso à Internet, produção de músicas ou imagens 3D e muito mais. Se você for criar uma extensão do ToonTalk, por favor, compartilhe-a com a imensa comunidade ToonTalk enviando-a para support@toontalk.com. As extensões são implementadas como DLLs (dynamic link libraries) do Microsoft Windows. A biblioteca precisa apenas exportar um procedimento. O procedimento precisa ser do tipo: BOOL __declspec(dllexport) receive(HANDLE handle, void **data_in, char *types_in, char *label, char *country_code, void ***data_out, char **types_out, char **to_say, BOOL *ok_to_speak, HINSTANCE string_library); Se um pombo conectado a uma extensão for presenteado com uma caixa, então o destinatário associado ao pombo é chamado com os seguintes argumentos: HANDLE handle. Um handle associado ao pombo. Será NULL a menos que o pombo tenha sido criado por uma extensão. Usado, por exemplo, por uma extensão do arquivo para controlar o handle do arquivo. void **data_in data_in é um arranjo de ponteiros. Para ser interpretado conforme os tipos descritos abaixo. char *types_in Uma string terminada em null descrevendo os tipos de caixa do ToonTalk recebidas pelo pombo. L é para um inteiro longo a partir de um número pad do ToonTalk. S é para uma string para um texto pad do ToonTalk. H é para um handle de um pombo para uma extensão. Colchetes ([]) agrupam os elementos de uma caixa. Um sinal de subtração (-) indica um buraco vazio de uma caixa. B indica um pombo normal.? é para todos os outros objetos do ToonTalk. Para L, S, B, - e ? há um item de dado correspondente no argumento de dado descrito acima. Os elementos de uma caixa dentro de outra caixa ocorrem no lugar de data_in. Um handle (H) requer 3 itens de dados: o procedimento recebedor, o handle associado e uma string que identifica o handle. char *label Uma string terminada em null identificando seu pombo. Pode ser vista normalmente na camiseta do pombo. char *country_code Uma string de letras terminada em 2 indicando o código do país da sua versão do ToonTalk. Por exemplo, "US", "UK", "SE", "DE" e "BR". Este argumento é fornecido no caso de a extensão exigir que o Márcio fale ou coloque uma caixa de diálogo de modo sensível à linguagem. void ***data_out Este é um arranjo de ponteiros – uma para cada pombo na caixa dada ao pombo de extensão. Isto permite que uma extensão especifique quais itens precisam ser dados aos pombos que as recebem. Cada elemento de data_out precisa ser definido para outro arranjo de ponteiros, cujo tamanho e elementos são consistentes com os elementos correspondentes em types_out (descrito abaixo). Note que o armazenamento alocado para os valores de types_out precisam ser alocados na heap global do Windows. (Por exemplo, usando GlobalAlloc.) char **types_out Este é um arranjo de ponteiros – uma para cada pombo na caixa dada ao pombo de extensão. Para especificar o que um pombo precisa receber, configure o elemento correspondente (sua ocorrência enquanto faz a leitura da esquerda para a direita) para uma string terminada em null alocada globalmente que descreve os tipos exatamente da mesma maneira que types_in. Para cada elemento em types_out, um item do ToonTalk é criado utilizando-se os dados em data_out. char **to_say Deve ser configurado para uma string terminada em null alocada globalmente se a extensão quiser que Márcio diga algo. BOOL *ok_to_speak Este deve ser configurado como não-zero se, quando Márcio for falar a string to_say, ele precisar usar um mecanismo de text-to-speech. Caso não configure, Márcio usará os balões de diálogo. HINSTANCE string_library Este é um handle da string de recurso de DLL carregada atualmente no ToonTalk. Deve ser ignorado a menos que o gravador da extensão tenha acesso à tabela de strings do ToonTalk. Returns. O procedimento recebedor precisa retornar não-zero, caso as variáveis data_out e types_out tenham sido configuradas. Remarks. Se types_in for NULL, o procedimento é chamado para que Márcio possa descrever o que esse pombo faz. Se types_in for "H", então o último pombo associado ao handle será destruído. Aqui está uma oportunidade para limpar (por exemplo, fechar o arquivo de handles). O arquivo DEF para a DLL precisa conter a seguinte linha: EXPORTS receive@1 A DLL deve ser nomeada como "TT" seguida pelo nome de extensão. Se a DLL vai ser usada pela versão 16-bit do ToonTalk, ela deve ser nomeada "T16" seguida pela extensão do nome. Basta incluir o arquivo de DLL no diretório do ToonTalk para instalá-la. Código de exemplo. Veja a seguir uma definição de exemplo de uma extensão de arquivo escrita em C++ (embora fique um pouco diferente, ele também pode ser definido em C). // Copyright (c) 1992,1998. Ken Kahn, Animated Programs, Todos os direitos reservados. // Você pode copiar e modificar este arquivo desde que mantenha este termo de copyright. #include <windows.h> extern "C" int __declspec(dllexport) WEP (int nParam); extern "C" BOOL __declspec(dllexport) receive(HANDLE handle, void **data, char *types, void ***out, char **out_types, char **to_say, HINSTANCE string_library); int FAR PASCAL LibMain (HANDLE , WORD , WORD , LPSTR ) { } int __declspec(dllexport) WEP (int) { } char *copy_string(char *source, int length) { if (length <= 0) length = strlen(source); char *destination = (char *) GlobalAlloc(0,length+1); // Não pode usar armazenamento local da biblioteca memcpy(destination,source,length); destination[length] = '\0'; // finaliza a string return(destination); }; // Este procedimento de recebimento está associado a arquivos abertos BOOL file_receive(HANDLE handle, void **data, char *types, char *label, char *country_code, void ***out, char **out_types, char **to_say, BOOL *ok_to_speak, HINSTANCE string_library) {
}; // Aqui está o procedimento exportado para abrir handles de arquivo BOOL __declspec(dllexport) receive(HANDLE handle, void **data, char *types, char *label, char *country_code, void ***out, char **out_types, char **to_say, BOOL *ok_to_speak, HINSTANCE string_library) { return(TRUE); }; if (strcmp(types,"[SSB]") == 0) { DWORD creation; char *device_control_string = NULL; char name[MAX_PATH]; if (stricmp(selector,"Create File") == 0) { // recebeu uma caixa com "Create File", seguida pelo nome do arquivo, seguido por um pombo strcpy(name,(char *) data[1]); } else if (stricmp(selector,"Open") == 0) { // recebeu uma caixa com "Open", seguido pelo nome do arquivo, seguido por um pombo
} else {
}; HANDLE file= CreateFile(name,GENERIC_READ|GENERIC_WRITE,0,NULL,creation FILE_ATTRIBUTE_NORMAL,NULL); if (file == INVALID_HANDLE_VALUE) { }; // dê ao pombo no terceiro buraco uma caixa com um novo pombo que está associado ao handle de arquivo out_types[0] = copy_string("[H]",3); out[0] = (void * *) GlobalAlloc(0,3*sizeof(void*)); out[0][0] = (void *) file_receive; // comportamento definido acima out[0][1] = (void *) file; // handle d arquivo out[0][2] = copy_string(name,0); // use o nome do arquivo como um rótulo return(TRUE); } else if (strcmp(types,"H") == 0) { // destruído }; // Configure *to_say para dar ajuda return(FALSE); |