home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / xacclib / xacctest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  12.6 KB  |  445 lines

  1. /* XACCTEST.PRG/ACC - ein XACC-Beispiel und Testprogramm
  2.     (c) 1993 Harald Sommerfeldt @ KI
  3.     E-Mail:  Harald_Sommerfeldt@ki.maus.de
  4. */
  5.  
  6. /* Geschichte:
  7.     22.03.93: erste Version
  8.     05.09.93: erste veröffentlichte Version
  9.     09.09.93: läuft nun auch unter Speicherschutz (MiNT)
  10.     04.10.93: Anpassung an GNU-C (16-Bit int) von Christian Felsch @ HH
  11.     31.10.93: Anpassung an GNU-C (32-Bit int), verwendet xacc_send() und xacc_decode()
  12. */
  13.  
  14. /* Hinweise:
  15.     - dieses Programm läuft sowohl als ACC als auch als PRG
  16.     - dieses Programm wurde mit Tabweite 3 entwickelt
  17. */
  18.  
  19.  
  20. #ifdef __PUREC__
  21. #include <aes.h>
  22. #include <tos.h>
  23. #endif
  24.  
  25. #ifdef __GNUC__
  26. #include <aesbind.h>
  27. #include <osbind.h>
  28. #define FO_READ    0                /* für Fopen */
  29. extern int    _app;
  30. #endif
  31.  
  32. #include <stdarg.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include "xacc.h"
  36. #include "xacctest.h"
  37.  
  38. typedef enum { FALSE, TRUE } bool;
  39.  
  40. int    ap_id, menu_id;            /* AES Application-ID und Menu-ID */
  41. OBJECT *menu;                        /* Menübaum */
  42. char    path[128], name[64];        /* für fsel_input() */
  43.  
  44. bool    handle_mesag( const int *msgbuf );
  45.  
  46.  
  47. /* form_alert() mit Format-String & wind_update() */
  48. int    form_falert( int defbut, const char *fastring, ... )
  49. {
  50.     va_list    argpoint;
  51.     static char buffer[256];
  52.     int    button;
  53.  
  54.     va_start( argpoint, fastring );
  55.     vsprintf( buffer, fastring, argpoint );
  56.     wind_update( BEG_UPDATE );
  57.     button = form_alert( defbut, buffer );
  58.     wind_update( END_UPDATE );
  59.     va_end( argpoint );
  60.     return button;
  61. }
  62.  
  63. /* vereinfachtes rsrc_gaddr() */
  64. OBJECT    *rsrc_gtaddr( int index )
  65. {
  66.     OBJECT    *tree;
  67.  
  68.     rsrc_gaddr( 0, index, &tree );
  69.     return tree;
  70. }
  71.  
  72.  
  73. /* dem Benutzer eine Liste der aktiven XACC-Applikationen anbieten;
  74.    diese Routine kann nur max. 8 Einträge verwalten (in einem richtigen
  75.    Programm sollte man natürlich alle anbieten), damit sie kurz und
  76.    knapp (und verständlich) bleibt
  77.     info   : Infozeile, worum es überhaupt geht
  78.     groups : Bitmaske, welche Groups wir brauchen
  79.     zurückgegeben wird der Index des XACC-Eintrages oder NIL (-1) */
  80. #define NXACC 8    /* soviele Einträge passen in unsere Liste */
  81. int    do_list( const char *info, unsigned groups )
  82. {
  83.     OBJECT    *dialog = rsrc_gtaddr( XACCLIST );
  84.     int        obj, x, y, w, h;
  85.     int        i;
  86.  
  87.     /* Titel setzen und Unterstreichung anpassen */
  88.     dialog[XL_TITLE].ob_spec.free_string = (char *)info;
  89.     dialog[XL_TITUN].ob_width = dialog[XL_TITLE].ob_width / (int)strlen( "STRING" ) * (int)strlen( info );
  90.  
  91.     /* Einträge in die Liste eintragen */
  92.     for ( i = 0; i < NXACC; i++ ) {
  93.         if ( xaccs[i].id >= 0 ) {
  94.             sprintf( dialog[XL_ENTRY+i].ob_spec.tedinfo->te_ptext, "%-30s %2d %#06x",
  95.                 xaccs[i].name, xaccs[i].id, xaccs[i].groups );
  96.             if ( xaccs[i].groups & groups )
  97.                 dialog[XL_ENTRY+i].ob_state &= ~DISABLED;
  98.             else
  99.                 dialog[XL_ENTRY+i].ob_state |= DISABLED;
  100.         }
  101.         else {
  102.             sprintf( dialog[XL_ENTRY+i].ob_spec.tedinfo->te_ptext, "%-40s", "" );
  103.             dialog[XL_ENTRY+i].ob_state |= DISABLED;
  104.             dialog[XL_ENTRY+i].ob_state &= ~SELECTED;
  105.         }
  106.     }
  107.  
  108.     /* Dialog darstellen */
  109.     form_center( dialog, &x, &y, &w, &h );
  110.     wind_update( BEG_UPDATE );
  111.     form_dial( FMD_START, 0, 0, 0, 0, x, y, w, h );
  112.     objc_draw( dialog, 0, MAX_DEPTH, x, y, w, h );
  113.     obj = form_do( dialog, 0 );
  114.     dialog[obj].ob_state &= ~SELECTED;
  115.     if ( obj == XL_OK ) {
  116.         for ( i = 0; i < NXACC; i++ ) {
  117.             if ( dialog[XL_ENTRY+i].ob_state & SELECTED ) break;
  118.         }
  119.         if ( i == NXACC ) i = -1;
  120.     }
  121.     else i = -1;
  122.     form_dial( FMD_FINISH, 0, 0, 0, 0, x, y, w, h );
  123.     wind_update( END_UPDATE );
  124.  
  125.     /* Index zurückgeben */
  126.     return i;
  127. }
  128.  
  129. /* eine Taste mittels ACC_KEY versenden */
  130. void    do_key( int i )
  131. {
  132.     OBJECT    *dialog = rsrc_gtaddr( SENDKEY );
  133.     int        x, y, w, h;
  134.  
  135.     wind_update( BEG_UPDATE );
  136.     form_center( dialog, &x, &y, &w, &h );
  137.     form_dial( FMD_START, 0, 0, 0, 0, x, y, w, h );
  138.     objc_draw( dialog, 0, MAX_DEPTH, x, y, w, h );
  139.     wind_update( BEG_MCTRL );
  140.     xacc_send( xaccs[i].id, ACC_KEY, evnt_keybd(), NULL, 0L );
  141.     wind_update( END_MCTRL );
  142.     form_dial( FMD_FINISH, 0, 0, 0, 0, x, y, w, h );
  143.     wind_update( END_UPDATE );
  144. }
  145.  
  146. /* einen Text mittels ACC_TEXT versenden */
  147. void    do_text( int i )
  148. {
  149.     OBJECT    *dialog = rsrc_gtaddr( SENDTEXT );
  150.     int        x, y, w, h, obj;
  151.     char        *buffer;
  152.  
  153.     wind_update( BEG_UPDATE );
  154.     form_center( dialog, &x, &y, &w, &h );
  155.     form_dial( FMD_START, 0, 0, 0, 0, x, y, w, h );
  156.     objc_draw( dialog, 0, MAX_DEPTH, x, y, w, h );
  157.     obj = form_do( dialog, 0 );
  158.     dialog[obj].ob_state &= ~SELECTED;
  159.     if ( obj == STXT_OK ) {
  160.         buffer = xacc_malloc( 100 );
  161.         if ( buffer != NULL ) {
  162.             strcpy( buffer, dialog[STXT_TXT].ob_spec.tedinfo->te_ptext );
  163.             xacc_send( xaccs[i].id, ACC_TEXT, TRUE, buffer, strlen(buffer)+1 );
  164.         }
  165.         else form_falert( 1, "[3][* Fehler bei xacc_malloc()][ OK ]" );
  166.     }
  167.     form_dial( FMD_FINISH, 0, 0, 0, 0, x, y, w, h );
  168.     wind_update( END_UPDATE );
  169. }
  170.  
  171. /* ein Stück Datei versenden */
  172. int    do_sendpiece( int dest_id, int type, int das_ende, char *addr, long length )
  173. {
  174.     int    msgbuf[8], dummy, event, keycode;
  175.  
  176.     if ( xacc_send( dest_id, type, das_ende, addr, length ) ) {
  177.  
  178.         /* auf Bestätigung warten, Timeout: 30 Sekunden */
  179.         for (;;) {
  180.             event = evnt_multi( MU_MESAG|MU_KEYBD|MU_TIMER, 2, 1, 1,
  181.                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msgbuf, 30*1000, 0,
  182.                 &dummy, &dummy, &dummy, &dummy, &keycode, &dummy );
  183.  
  184.             /* UNDO gedrückt: keine Lust mehr */
  185.             if ( (event & MU_KEYBD) && keycode == 0x6100 ) {    /* UNDO */
  186.                 if ( form_falert( 1, "[2][ |Senden abbrechen?][Ja|Nein]" ) == 1 )
  187.                     break;
  188.             }
  189.  
  190.             /* eine Nachricht für uns */
  191.             if ( event & MU_MESAG ) {
  192.                 if ( msgbuf[0] == ACC_ACK ) {
  193.                     /* alles paletti: weiter im Text */
  194.                     if ( msgbuf[3] ) return TRUE;
  195.                     /* ansonsten: das Leben ist hart und ungerecht */
  196.                     form_falert( 1, "[3][ |Keiner mag mich!][Schnüff]" );
  197.                     break;
  198.                 }
  199.                 if ( msgbuf[0] != MN_SELECTED && msgbuf[0] != AC_OPEN )
  200.                     handle_mesag( msgbuf );
  201.             }
  202.  
  203.             /* 30 Sekunden vorbei: Timeout */
  204.             if ( event & MU_TIMER ) {
  205.                 form_falert( 1, "[3][ |Timeout beim Senden][Abbruch]" );
  206.                 break;
  207.             }
  208.         }
  209.     }
  210.  
  211.     return FALSE;
  212. }
  213.  
  214. /* eine Datei mittels 'message' versenden */
  215. void    do_sendfile( int i, const char *fileext, int message )
  216. {
  217.     char    fpath[128], *buffer;
  218.     int    button, fh;
  219.     long    l;
  220.  
  221.     /* ein wenig Vorbereitung für fsel_input()... */
  222.     if ( *path == '\0' ) {
  223.         path[0] = Dgetdrv() + 'A';
  224.         path[1] = ':';
  225.         Dgetpath( path+2, 0 );
  226.         strcat( path+2, "\\" );
  227.     }
  228.     strcat( strcpy( strrchr( path, '\\' ) + 1, "*." ), fileext );
  229.     if ( strchr( name, '.' ) != NULL ) strcpy( strchr( name, '.' ) + 1, fileext );
  230.  
  231.     /* Dateiauswahl aufrufen */
  232.     if ( fsel_input( path, name, &button ) && button ) {
  233.  
  234.         /* Bastelstunde: wir basteln und einen Dateinamen */
  235.         strcpy( strrchr( strcpy( fpath, path ), '\\' ) + 1, name );
  236.  
  237.         /* Handwerkerstunde: wir öffnen eine Datei */
  238.         if ( (l = Fopen( fpath, FO_READ )) >= 0L ) {
  239.             fh = (int)l;
  240.  
  241.             /* Programmierstunde: wir versenden eine Datei mittels XACC */
  242.             buffer = xacc_malloc( 1000L );
  243.             if ( buffer != NULL ) {
  244.  
  245.                 for (;;) {
  246.                     l = Fread( fh, 1000L, buffer );
  247.                     if ( l <= 0L ) {
  248.                         do_sendpiece( xaccs[i].id, message, TRUE, buffer, 0L );
  249.                         break;
  250.                     }
  251.                     if ( !do_sendpiece( xaccs[i].id, message, l < 1000L, buffer, l ) )
  252.                         break;
  253.                     if ( l < 1000L ) break;
  254.                 }
  255.                 Mfree( buffer );
  256.             }
  257.             else form_falert( 1, "[3][* Fehler bei xacc_malloc()][ OK ]" );
  258.  
  259.             Fclose( fh );
  260.         }
  261.     }
  262. }
  263.  
  264. /* eine GEM-Metadatei mittels ACC_META versenden */
  265. void    do_meta( int i )
  266. {
  267.     do_sendfile( i, "GEM", ACC_META );
  268. }
  269.  
  270. /* eine GEM-Imagedatei mittels ACC_IMG versenden */
  271. void    do_img( int i )
  272. {
  273.     do_sendfile( i, "IMG", ACC_IMG );
  274. }
  275.  
  276.  
  277. /* das Copyright des genialen & begnadeten Programmieres ausgeben :-) */
  278. void    do_info( void )
  279. {
  280.     form_falert( 1, "[1][ |XACC - Testprogramm|(c) 1993 Harald Sommerfeldt][  OK  ]" );
  281. }
  282.  
  283. /* der Hauptdialog, der in der ACC-Version die Menüzeile ersetzt */
  284. void    do_dialog( void )
  285. {
  286.     OBJECT    *dialog = rsrc_gtaddr( DIALOG );
  287.     int    x, y, w, h, obj;
  288.     int    i;
  289.  
  290.     wind_update( BEG_UPDATE );
  291.     form_center( dialog, &x, &y, &w, &h );
  292.     form_dial( FMD_START, 0, 0, 0, 0, x, y, w, h );
  293.     objc_draw( dialog, 0, MAX_DEPTH, x, y, w, h );
  294.     obj = form_do( dialog, 0 );
  295.     dialog[obj].ob_state &= ~SELECTED;
  296.     form_dial( FMD_FINISH, 0, 0, 0, 0, x, y, w, h );
  297.     wind_update( END_UPDATE );
  298.     switch ( obj ) {
  299.         case DO_INFO:
  300.             do_info();
  301.             break;
  302.         case DO_KEY:
  303.             if ( (i = do_list( "sende Taste ...", 1 )) >= 0 ) do_key( i );
  304.             break;
  305.         case DO_TEXT:
  306.             if ( (i = do_list( "sende Text ...", 1 )) >= 0 ) do_text( i );
  307.             break;
  308.         case DO_META:
  309.             if ( (i = do_list( "sende GEM-Metadatei ...", 2 )) >= 0 ) do_meta( i );
  310.             break;
  311.         case DO_IMG:
  312.             if ( (i = do_list( "sende GEM-Imagedatei ...", 2 )) >= 0 ) do_img( i );
  313.             break;
  314.     }
  315. }
  316.  
  317. /* GEM-Nachrichten Dispatcher, wird u.a. rekursiv von do_sendpiece() aufgerufen */
  318. bool    handle_mesag( const int *msgbuf )
  319. {
  320.     void    *addr;
  321.     long    length;
  322.     int    i, last_or_keycode;
  323.  
  324.     if ( !xacc_message( msgbuf ) ) switch ( msgbuf[0] ) {
  325.  
  326.         case AC_OPEN:                /* ACC-Eintrag angewählt */
  327.             if ( menu != NULL ) do_dialog();
  328.             else form_falert( 1, "[3][ |XACCTEST.RSC nicht geladen][Abbruch]" );
  329.             break;
  330.  
  331.         case MN_SELECTED:            /* Menüeintrag angeklickt */
  332.             switch( msgbuf[4] ) {
  333.                 case MINFO:
  334.                     do_info();
  335.                     break;
  336.                 case MS_KEY:
  337.                     if ( (i = do_list( "sende Taste...", 1 )) >= 0 ) do_key( i );
  338.                     break;
  339.                 case MS_TEXT:
  340.                     if ( (i = do_list( "sende Text...", 1 )) >= 0 ) do_text( i );
  341.                     break;
  342.                 case MS_META:
  343.                     if ( (i = do_list( "sende GEM-Metadatei...", 2 )) >= 0 ) do_meta( i );
  344.                     break;
  345.                 case MS_IMG:
  346.                     if ( (i = do_list( "sende GEM-Imagedatei...", 2 )) >= 0 ) do_img( i );
  347.                     break;
  348.                 case MQUIT:
  349.                     return FALSE;        /* Programmende */
  350.             }
  351.             menu_tnormal( menu, msgbuf[3], TRUE );
  352.             break;
  353.  
  354.         case ACC_ACK:
  355.             /* ein Empfänger will uns Kunde tun von seiner Begeisterung auf
  356.                 die ACC_TEXT, ACC_KEY, ACC_META oder ACC_IMG-Nachricht, die
  357.                 wir ihm geschickt hatten, msgbuf[3] enthält den
  358.                 Begeisterungsgrad: 0 (durchgefallen) oder 1 (bestanden) */
  359.             form_falert( 1, ( msgbuf[3] ) ? "[1][ |ACC_ACK TRUE|empfangen][  OK  ]"
  360.                                           : "[1][ |ACC_ACK FALSE|empfangen][  OK  ]" );
  361.             break;
  362.  
  363.         case ACC_TEXT:
  364.             /* es wird versucht, uns einen Text anzudrehen */
  365.             {    char    buffer[22];
  366.  
  367.                 xacc_decode( msgbuf, NULL, &addr, NULL );
  368.                 strncpy( buffer, addr, 20 )[20] = '\0';
  369.                 if ( form_falert( 1, "[1][ |ACC_TEXT \"%s\"|empfangen][OK|nicht OK]", buffer ) == 1 )
  370.                     xacc_ack( msgbuf[1], TRUE );
  371.                 else
  372.                     xacc_ack( msgbuf[1], FALSE );
  373.             }
  374.             break;
  375.         case ACC_KEY:
  376.             /* es wird versucht, uns eine Taste anzudrehen */
  377.             xacc_decode( msgbuf, &last_or_keycode, NULL, NULL );
  378.             if ( form_falert( 1, "[1][ |ACC_KEY %#06x|empfangen][OK|nicht OK]", last_or_keycode ) == 1 )
  379.                 xacc_ack( msgbuf[1], TRUE );
  380.             else
  381.                 xacc_ack( msgbuf[1], FALSE );
  382.             break;
  383.         case ACC_META:
  384.             /* es wird versucht, uns eine GEM-Metadatei anzudrehen */
  385.             xacc_decode( msgbuf, &last_or_keycode, &addr, &length );
  386.             if ( form_falert( 1, "[1][ |ACC_META %d %p %ld|empfangen][OK|nicht OK]",
  387.                                  last_or_keycode, addr, length ) == 1 )
  388.                 xacc_ack( msgbuf[1], TRUE );
  389.             else
  390.                 xacc_ack( msgbuf[1], FALSE );
  391.             break;
  392.         case ACC_IMG:
  393.             /* es wird versucht, uns eine GEM-Imagedatei anzudrehen */
  394.             xacc_decode( msgbuf, &last_or_keycode, &addr, &length );
  395.             if ( form_falert( 1, "[1][ |ACC_IMG %d %p %ld|empfangen][OK|nicht OK]",
  396.                                  last_or_keycode, addr, length ) == 1 )
  397.                 xacc_ack( msgbuf[1], TRUE );
  398.             else
  399.                 xacc_ack( msgbuf[1], FALSE );
  400.             break;
  401.  
  402.     }
  403.     return TRUE;
  404. }
  405.  
  406. /* und hier nun die Krönung: das Hauptprogramm */
  407. int    main( void )
  408. {
  409.     const char xaccname[] = "XACC-Testprogramm";
  410.     int    msgbuf[8];
  411.  
  412.     ap_id = appl_init();
  413.     if ( !_app ) menu_id = menu_register( ap_id, "  XACC-Testprogramm" );
  414.     else menu_id = -1;
  415.  
  416.     wind_update( BEG_UPDATE );
  417.     if ( rsrc_load( "XACCTEST.RSC" ) ) {
  418.         menu = rsrc_gtaddr( MENU );
  419.         rsrc_gtaddr( SENDTEXT )[STXT_TXT].ob_spec.tedinfo->te_ptext[0] = '\0';
  420.     }
  421.     else menu = NULL;
  422.     if ( _app ) {    /* Ich Programm? Du Menüzeile darstellen! */
  423.         if ( menu != NULL ) {
  424.             menu_bar( menu, TRUE );
  425.             graf_mouse( ARROW, NULL );
  426.         }
  427.         else form_falert( 1, "[3][ |XACCTEST.RSC nicht geladen][Abbruch]" );
  428.     }
  429.     wind_update( END_UPDATE );
  430.  
  431.     /* XACC-Protokoll anwerfen */
  432.     xacc_init( menu_id, xaccname, (int)sizeof(xaccname), 0x0003 );
  433.  
  434.     for (;;) {
  435.         evnt_mesag( msgbuf );                        /* auf Nachricht warten */
  436.         if ( !handle_mesag( msgbuf ) ) break;    /* und auswerten */
  437.     }
  438.  
  439.     /* XACC-Protokoll abmelden */
  440.     xacc_exit();
  441.  
  442.     appl_exit();
  443.     return 0;
  444. }
  445.