/**************************************************************** * * Name: REQUEST * * Function: Provides a front-end for the SERVER program. * Takes a string entered by the user and sends * requests to the SERVER to either add the string * to the database or find all records that contain * the string. * * Shows how to: 1. find a named mailbox. * 2. read a key-at-a-time from the keyboard. * 3. use an asynchronous notify function to * detect attempts to close the window. * ****************************************************************/ #include #include "dvapi.h" /* minimum API level required */ #define required 0x201 /* public name of file server mailbox */ char mbname[] = "Example File Server"; int lmbname = sizeof(mbname); /* status values for messages to the server */ #define LOGON 1 #define LOGOFF 2 #define ADDREC 3 #define QUERY 4 /* status values for messages from the server */ #define LOGGED_ON 1 #define LOGGED_OFF 2 #define READY 3 #define FOUND 4 /* keyboard codes returned by key_getc() */ #define BACKSPACE 8 #define ENTER_KEY 13 #define F1_KEY 0x3B+256 #define F2_KEY 0x3C+256 /* object handles */ ulong win,kbd,mal,server,obj; /* variables used to receive mail */ char *mptr; int mlng,status; /* user input buffer and character counter */ char inbuf[80],*inptr; int nchars; /* message displayed if the server is not present */ char need_server_msg[] = "Please load the SERVER program.\n"; /* message displayed once the server acknowledges logon */ char logged_on_msg[] = "\ File server is ready.\n\ To query: type a search string followed by ENTER.\n\ To add a record: type the record followed by F1.\n\ To auto-query: type F2.\n"; /* other variables */ int version,auto_query = 0; int notify_function(); /********************************************************************** * main - check for DESQview present and enable required extensions. ***********************************************************************/ main () { /* initialize C interfaces and get API version number */ version = api_init(); /* if DESQview is not running or version is too low, display a message */ if (version < required) { printf ("This program requires DESQview version %d.02%d or later.\n", required/256,required%256); } /* tell DESQview what extensions to enable and start application */ else { api_level (required); program_body(); } /* disable C interfaces and return from program */ api_exit(); } /******************************************************************** /* program_body /* /* Locate the file server. Sit in a loop sending requests and /* processing responses. Ask for notification when the user tries /* to close the window and notify the server before actually closing. /********************************************************************/ program_body () { /* get handles of default objects */ win = win_me(); kbd = key_me(); mal = mal_me(); /* find the server's named mailbox. If it is not present, prompt the /* user to load SERVER. Loop until found. */ server = mal_find (mbname,lmbname); if (server == 0) win_swrite (win,need_server_msg); while (server == 0) { api_pause(); server = mal_find (mbname,lmbname); } /* ask for asynchronous notification on CLOSE requests */ win_async (win,notify_function); win_notify (win,NTF_CLOSE); /* ask server for logon, wait for reply, and display instructions */ mal_addto (server,NULL,0,LOGON); status = mal_read (mal,&mptr,&mlng); win_swrite (win,logged_on_msg); /* send a request to the server. Display each message received from the /* server until one is received with the READY status. Loop. */ while (1) { send_request(); while (1) { status = mal_read (mal,&mptr,&mlng); if (status == READY) break; win_write (win,mptr,mlng); win_swrite (win,"\n"); } } } /******************************************************************** /* send_request /* /* This function writes a prompt and processes user input. The easiest /* way to take user input is to use an input field and let DESQview /* handle entry editing. We do it manually here to show how keystroke /* mode can be used in situations where fields are inappropriate (such /* as when writing a text editor). /********************************************************************/ send_request () { int k,req,row,col; /* write the prompt and display the cursor */ win_swrite (win,"\n? "); win_hcur (win); /* initialize the input buffer variables */ inptr = inbuf; nchars = 0; /* gather keys until "break" or until 80 characters have been typed */ while (nchars < 80) { /* if in auto_query mode and there is no pending keyboard input, /* fake a query for the string "time" */ if (auto_query) { if (key_sizeof (kbd) == 0) { win_swrite (win,"time"); strcpy (inbuf,"time\0"); req = QUERY; break; } /* any key typed while in auto_query mode terminates the mode /* and is dropped */ else { auto_query = 0; k = key_getc (kbd); } } /* wait for next key */ k = key_getc(kbd); /* if normal key - add to buffer, display, and update cursor */ if ((k>31) && (k<256)) { *inptr++ = k; nchars += 1; win_putc (win,k,7); win_hcur (win); } /* if ENTER - terminate input string and setup to send QUERY message */ else if (k == ENTER_KEY) { *inptr = 0; req = QUERY; break; } /* if F2 - enter auto_query mode */ else if (k == F2_KEY) { auto_query = 1; } /* if F1 - terminate input string and setup to send ADDREC message */ else if (k == F1_KEY) { *inptr = 0; req = ADDREC; break; } /* if BACKSPACE - backup one char in input buffer and in the window */ else if (k == BACKSPACE) { qry_cursor (win,&row,&col); if (col > 2) { nchars -= 1; inptr -= 1; win_cursor (win,row,col-1); win_blanks (win,1); win_cursor (win,row,col-1); win_hcur (win); } } } /* send the resulting request to the server and write a carriage return /* to the window */ mal_addto (server,inbuf,strlen(inbuf)+1,req); win_swrite (win,"\n"); } /******************************************************************** /* notify_function /* /* This function is called as a "software interrupt" whenever the /* window manager sends a notify message. Since we have only requested /* notification on CLOSE requests, we do not need to check the type /* of notify. All we do is send a message to the server requesting /* a logoff and wait for confirmation. Any mail received in the /* meantime is ignored. When confirmation arrives, we free our task /* window. /********************************************************************/ notify_function () { mal_addto (server,NULL,0,LOGOFF); while (mal_read (mal,&mptr,&mlng) != LOGGED_OFF) {}; api_exit(); win_free (win); }