]> git.cworth.org Git - ttt/blob - src/ttt-curses-client.c
Add a dependency of ttt-client.c on ttt-lex.h to fix the build.
[ttt] / src / ttt-curses-client.c
1 /*ttt-curses-client.c - curses based tic-tac-toe game client
2  *
3  * Copyright © 2005 Bryan Worth
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Author: Bryan Worth <bryan@theworths.org> 
20  */
21
22 /* TODO: see /usr/share/doc/ncurses-devel-5.3/test/view.c for example code
23  *       to handle window resizing
24  *
25  */      
26
27 #include "ttt-socket.h"
28 #include <curses.h>
29 #include <signal.h>
30
31 static void
32 finish (int sig);
33
34 void
35 mvprintstr (int     y,
36             int     x,
37             char    *string,
38             chtype  attrs);
39
40 void
41 mvwprintstr (WINDOW *window,
42              int    y,
43              int    x,
44              char   *string,
45              chtype attrs);
46
47 void
48 wprint (WINDOW *window,
49         char   *string);
50
51 /*
52  *
53  */
54
55 void
56 mvprintstr (int    y,
57             int    x,
58             char   *string,
59             chtype attrs)
60 {
61     int xx = 0;
62     int l;
63     chtype cline[1000];
64     l = strlen(string);
65     while (xx < l) {
66         cline[xx] = string[xx] | attrs;
67         xx++;
68     }
69     cline[l] = '\0';
70     mvaddchstr (y, x, cline);
71 }
72
73 void mvwprintstr (WINDOW *window,
74                   int    y,
75                   int    x,
76                   char   *string,
77                   chtype attrs)
78 {
79     int xx = 0;
80     int l;
81     chtype cline[1000];
82     l = strlen (string);
83     while (xx < l) {
84         cline[xx] = string[xx] | attrs;
85         xx++;
86     }
87     cline[l] = '\0';
88     mvwaddchstr (window, y, x, cline);
89 }
90
91 void wprint (WINDOW *window,
92              char   *string)
93 {
94     int xx = 0;
95     int l;
96     chtype outc;
97     l = strlen (string);
98
99     while (xx < l) {
100         outc = string[xx];
101         if (string[xx] != '\r') 
102             waddch (window, outc);
103         xx++;
104     }
105 }
106
107 void inpprint (WINDOW *window,char *string,int pos,int curx);
108
109 void inpprint (WINDOW *window,char *string,int pos,int curx)
110 {
111     int mx,my;
112     char tbuf[1024];
113     getmaxyx(window,my,mx);
114     if ( curx > 0 ) {
115         strncpy(tbuf,&string[curx], mx-1);
116         tbuf[mx-1]='\0';
117         wmove(window,0,0);
118         wprint(window,tbuf);
119         wclrtoeol(window);
120         wmove(window,0,pos - curx);
121         
122     }
123     else
124     {
125         strcpy(tbuf,string);
126         if (strlen(string) > mx-1) tbuf[mx-1]='\0';
127         wmove(window,0,0);
128         wprint(window,tbuf);
129         wclrtoeol(window);
130         wmove(window,0,pos);
131     }
132
133
134 }
135
136
137
138
139 FILE *sockin, *sockout;
140
141
142 int
143 main (int argc, char **argv)
144 {
145     char *host="localhost";
146     char *port="5334";
147     chtype c;
148     char *username;
149     char *envuser;
150     char *confpath;
151     char *conffile;
152     char *command_string;
153     int _socket;
154     char buffer[BUFSIZ];
155     char tlin[1024];
156     char inplin[1024];
157     ttt_status_t status;
158     int curpos = 0;
159     int curx = 0;
160     int mx, my;
161
162     static WINDOW *mainwnd;
163     static WINDOW *dispwin;
164     static WINDOW *inpwin;
165     static WINDOW *statwin;
166     FILE *conf_file;
167
168     mainwnd = initscr();
169     int dlines = LINES, cols = COLS;
170
171     (void) nonl ();
172     (void) nl ();
173     noecho ();
174     cbreak ();
175     nodelay (mainwnd, TRUE);
176     curs_set (0);
177     refresh ();
178     dispwin = newwin (dlines - 6, cols , 0, 0);
179     statwin = newwin (4, cols , dlines -4, 0);
180     inpwin = newwin (1, cols , dlines -1, 0);
181     keypad (mainwnd, TRUE);     // enable keyboard mapping 
182     keypad (inpwin, TRUE);      // enable keyboard mapping 
183     nodelay (inpwin, TRUE);
184     getmaxyx(inpwin,my,mx);
185     wrefresh (mainwnd);
186     wrefresh (dispwin);
187     wrefresh (statwin);
188     wrefresh (inpwin);
189     (void) scrollok (mainwnd, TRUE);
190     (void) scrollok (dispwin, TRUE);
191     (void) scrollok (statwin, TRUE);
192     (void) scrollok (inpwin, TRUE);
193     (void) idlok (mainwnd, TRUE);
194     (void) idlok (dispwin, TRUE);
195     (void) idlok (statwin, TRUE);
196     (void) idlok (inpwin, TRUE);
197     wsetscrreg (dispwin, 0, dlines - 2);
198     wsetscrreg (statwin, 0, 4);
199     
200     (void) signal (SIGINT, finish);     /* arrange interrupts to terminate */
201     if (has_colors ()) {
202         start_color ();
203
204         init_pair (COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
205         init_pair (COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
206         init_pair (COLOR_RED, COLOR_RED, COLOR_BLACK);
207         init_pair (COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
208         init_pair (COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
209         init_pair (COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
210         init_pair (COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
211         init_pair (COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
212     }
213     wrefresh (dispwin);
214     wrefresh (inpwin);
215
216     xasprintf(&confpath,"%s/.ttt/",getenv("HOME"));
217     xasprintf(&conffile,"%s/.ttt/client.conf",getenv("HOME"));
218     username="user";
219     if (access (conffile, F_OK) != 0 ) {
220         envuser=getenv("USER");
221         if (envuser != NULL) username=strdup(envuser);
222         if (access (confpath, F_OK) != 0 ) {
223             xasprintf(&command_string,"mkdir %s",confpath);
224             system (command_string);
225         }
226         if ((conf_file = fopen(conffile,"w")) != NULL) {
227             fprintf(conf_file,"username=%s",username);
228             fclose(conf_file);
229         }
230     }
231     if ((conf_file = fopen(conffile,"r")) != NULL) {
232         while (fgets(buffer,BUFSIZ,conf_file)) {
233             if (buffer[strlen(buffer)-1] == 10) buffer[strlen(buffer)-1] = '\0';
234             if (strncmp(buffer,"username=",9) == 0) {
235                 xasprintf (&username, "%s", &buffer[9]);
236             }
237             if (strncmp(buffer,"port=",5) == 0) {
238                 xasprintf (&port, "%s",&buffer[5]);
239             }
240         }
241         fclose(conf_file); 
242     }
243     status=ttt_socket_create_client (host, port, &_socket);
244     if (status) {
245         endwin();
246         printf("Unable to connect to server! Connection status: %d\n",status);
247         exit(1);
248     }
249     sockin=fdopen(_socket,"r");
250     sockout=fdopen(_socket,"w");
251
252
253
254     fprintf(sockout, "HELO %s\r\n",username);
255     fflush(sockout);
256     
257     if (fgets(buffer,BUFSIZ,sockin)) {
258         if ((strncmp(buffer,"NOTICE MESSAGE ",15) == 0) && (strlen(buffer) > 15)) {
259             wprint (dispwin, buffer);
260         }
261         else {
262             if (strncmp(buffer,"MESSAGE",7) != 0) wprint (statwin, buffer);
263         }
264         wrefresh (dispwin);
265         wrefresh (statwin);
266     }
267     
268     fprintf(sockout, "WHO \r\n");
269     fflush(sockout);
270     
271     inplin[0]='\0';
272     while (1) {
273         curs_set (1);
274         c = wgetch (inpwin);
275         if ((c != ERR) && (strlen(inplin)< 1000)) {
276             switch ((int) c) {
277             case 13:  // CARRIAGE RETURN
278                 break;
279             case 10: // LINE FEED
280                 break;
281             case 262: // HOME key
282                 curpos = 0;
283                 curx = 0;
284                 inpprint(inpwin,inplin,curpos,curx);
285                 wrefresh (inpwin);
286                 break;       
287             case 360: // END key
288                 curpos = strlen(inplin);
289                 if (strlen(inplin) > mx -1) {
290                     curx = strlen(inplin) - mx +1;
291                 }
292                 else
293                 {
294                     curx = 0;
295                 }
296                 inpprint(inpwin,inplin,curpos,curx);
297                 wrefresh (inpwin);
298                 break;
299             case 330: // DELETE key
300                 if (strlen(inplin) > 0) {
301                     if (curpos == strlen(inplin)) {
302                         inplin[strlen(inplin)-1]='\0';
303                         curpos--;
304                     }
305                     else
306                     {
307                         strncpy(&inplin[curpos],&inplin[curpos+1],strlen(inplin)-curpos+1);
308                     }
309
310
311                     inpprint(inpwin,inplin,curpos,curx);
312                     wrefresh (inpwin);
313                 }
314                 break;          
315             case 263: //  }
316             case 8:   //   > Various BACKSPACE codes
317             case 127: //  }
318                 if (curpos > 0) {
319                     if (curpos == strlen(inplin)) {
320                         inplin[strlen(inplin)-1]='\0';
321                     }
322                     else
323                     {
324                         strncpy(&inplin[curpos-1],&inplin[curpos],strlen(inplin)-curpos);
325                         inplin[strlen(inplin)-1]='\0';
326                     }
327                     if (curpos > 0) curpos--;
328                     if (curx > 0) curx--;
329                     inpprint(inpwin,inplin,curpos,curx);
330                     wrefresh (inpwin);
331                 }
332                 break;
333             case 260: // LEFT ARROW
334                 if (curpos > 0) {
335                     curpos--;
336                     if (curx > curpos) curx = curpos;
337                     inpprint(inpwin,inplin,curpos,curx);
338                     wrefresh (inpwin);
339                 }
340                 break;
341             case 261: // RIGHT ARROW
342                 if (curpos < strlen(inplin)) {
343                     curpos++;
344                     if (curpos - curx > mx-1) curx++;
345                     inpprint(inpwin,inplin,curpos,curx);
346                     wrefresh (inpwin);
347                 }
348                 break;
349             default: // ALL OTHER KEYS
350                 if (curpos == strlen(inplin)) {
351                     sprintf (inplin,"%s%c",inplin,(int) c);
352                 }
353                 else
354                 {
355                     
356                     strncpy(tlin,&inplin[curpos],strlen(inplin)-curpos);
357                     tlin[strlen(inplin)-curpos]='\0';
358                     strcpy(&inplin[curpos+1],tlin);
359                     inplin[curpos] = (int) c;
360                 }
361                 curpos++;
362                 if (curpos - curx > mx-1) curx++;
363                 inpprint(inpwin,inplin,curpos,curx);
364                 wrefresh (inpwin);
365             }
366         }
367
368         if (fgets(buffer,BUFSIZ,sockin)) {
369             curs_set (0);
370             if ((strncmp(buffer,"NOTICE MESSAGE ",15) == 0) && (strlen(buffer) > 15)) {
371                 wprint (dispwin, &buffer[15]);
372             }
373             else {
374                 if (strncmp(buffer,"MESSAGE",7) != 0) wprint (statwin, buffer);
375             }
376             wrefresh (dispwin);
377             wrefresh (statwin);
378             wrefresh (inpwin);
379         }
380         if (((int) c == 13) || ((int) c == 10)) {
381             curs_set (0);
382             curpos = 0;
383             curx = 0;
384             if (inplin[0] == '/') {
385                 fprintf(sockout,"%s\r\n",&inplin[1]);
386             }
387             else {
388                 fprintf(sockout,"MESSAGE \"%s\"\r\n",inplin);
389             }
390             fflush(sockout);
391             inplin[0] = '\0';
392             if (fgets(buffer,BUFSIZ,sockin)) {
393                 if ((strncmp(buffer,"NOTICE MESSAGE ",15) == 0) && (strlen(buffer) > 15)) {
394                     wprint (dispwin, buffer);
395                 }
396                 else {
397                     if (strncmp(buffer,"MESSAGE",7) != 0) wprint (statwin, buffer);
398                 }
399             }
400             wrefresh (dispwin);
401             wrefresh (statwin);
402             werase (inpwin);
403             wrefresh (inpwin);
404         }
405     }
406 }
407
408 static void
409 finish (int sig)
410 {
411     char buffer[BUFSIZ];
412     
413     endwin();
414
415     /* do your non-curses wrapup here */
416     fprintf(sockout,"QUIT\r\n");
417     fflush(sockout);
418
419     while (fgets(buffer,BUFSIZ,sockin));
420     exit (0);
421 }