|
|
1.1 root 1: #line 1 "MISC.C"
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: /***************************************************************************/
6: /* Miscellaneous functions that are useful many places throughout the code */
7: /***************************************************************************/
8:
9: #include "sbbs.h"
10: #include "crc32.h"
11:
12: #ifdef __WIN32__
13: #include <windows.h> // Required for kbd_state(), beep(), and mswait()
14: #endif
15:
16: /****************************************************************************/
17: /* Returns the number of characters in 'str' not counting ctrl-ax codes */
18: /* or the null terminator */
19: /****************************************************************************/
20: int bstrlen(char *str)
21: {
22: int i=0;
23:
24: while(*str) {
25: if(*str==1) /* ctrl-a */
26: str++;
27: else
28: i++;
29: if(!(*str)) break;
30: str++; }
31: return(i);
32: }
33:
34: void strip_ctrl(char *str)
35: {
36: char tmp[1024];
37: int i,j,k;
38:
39: k=strlen(str);
40: for(i=j=0;i<k;i++)
41: if(str[i]==1) /* Ctrl-a */
42: i++;
43: else if(j && str[i]<=SP && tmp[j-1]==SP)
44: continue;
45: else if(i && !isalnum(str[i]) && str[i]==str[i-1])
46: continue;
47: else if((uchar)str[i]>=SP)
48: tmp[j++]=str[i];
49: else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
50: tmp[j++]=SP;
51: tmp[j]=0;
52: strcpy(str,tmp);
53: }
54:
55: void strip_exascii(char *str)
56: {
57: char tmp[1024];
58: int i,j,k;
59:
60: k=strlen(str);
61: for(i=j=0;i<k;i++)
62: if(!(str[i]&0x80))
63: tmp[j++]=str[i];
64: tmp[j]=0;
65: strcpy(str,tmp);
66: }
67:
68: /****************************************************************************/
69: /* Returns in 'string' a character representation of the number in l with */
70: /* commas. */
71: /****************************************************************************/
72: char *ultoac(ulong l, char *string)
73: {
74: char str[256];
75: char i,j,k;
76:
77: ultoa(l,str,10);
78: i=strlen(str)-1;
79: j=i/3+1+i;
80: string[j--]=0;
81: for(k=1;i>-1;k++) {
82: string[j--]=str[i--];
83: if(j>0 && !(k%3))
84: string[j--]=','; }
85: return(string);
86: }
87:
88: /****************************************************************************/
89: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */
90: /* number of times if the attempted file is already open or denying access */
91: /* for some other reason. All files are opened in BINARY mode. */
92: /****************************************************************************/
93: int nopen(char *str, int access)
94: {
95: char logstr[256];
96: int file,share,count=0;
97:
98: if(access&O_DENYNONE) {
99: share=SH_DENYNO;
100: access&=~O_DENYNONE; }
101: else if(access==O_RDONLY) share=SH_DENYWR;
102: else share=SH_DENYRW;
103: while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
104: && errno==EACCES && count++<LOOP_NOPEN)
105: if(count>10)
106: mswait(55);
107: if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN) {
108: sprintf(logstr,"NOPEN COLLISION - File: %s Count: %d"
109: ,str,count);
110: logline("!!",logstr); }
111: if(file==-1 && errno==EACCES)
112: bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
113: return(file);
114: }
115:
116: /****************************************************************************/
117: /* This function performs an nopen, but returns a file stream with a buffer */
118: /* allocated. */
119: /****************************************************************************/
120: FILE *fnopen(int *file, char *str, int access)
121: {
122: char mode[128];
123: FILE *stream;
124:
125: if(((*file)=nopen(str,access))==-1)
126: return(NULL);
127:
128: if(access&O_APPEND) {
129: if(access&O_RDONLY)
130: strcpy(mode,"a+");
131: else
132: strcpy(mode,"a"); }
133: else {
134: if(access&O_WRONLY)
135: strcpy(mode,"r+");
136: else
137: strcpy(mode,"r"); }
138: stream=fdopen((*file),mode);
139: if(stream==NULL) {
140: close(*file);
141: errormsg(WHERE,ERR_FDOPEN,str,access);
142: return(NULL); }
143: setvbuf(stream,NULL,_IOFBF,2*1024);
144: return(stream);
145: }
146:
147: #ifndef __FLAT__
148: /****************************************************************************/
149: /* This function reads files that are potentially larger than 32k. */
150: /* Up to one megabyte of data can be read with each call. */
151: /****************************************************************************/
152: long lread(int file, char huge *buf,long bytes)
153: {
154: long count;
155:
156: for(count=bytes;count>32767;count-=32767,buf+=32767)
157: if(read(file,(char *)buf,32767)!=32767)
158: return(-1L);
159: if(read(file,(char *)buf,(int)count)!=count)
160: return(-1L);
161: return(bytes);
162: }
163:
164: long lfread(char huge *buf, long bytes, FILE *fp)
165: {
166: long count;
167:
168: for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
169: if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
170: return(0);
171: if(fread((char *)buf,1,(int)count,fp)!=count)
172: return(0);
173: return(bytes);
174: }
175:
176: /****************************************************************************/
177: /* This function writes files that are potentially larger than 32767 bytes */
178: /* Up to one megabytes of data can be written with each call. */
179: /****************************************************************************/
180: long lwrite(int file, char huge *buf, long bytes)
181: {
182:
183: long count;
184:
185: for(count=bytes;count>32767;count-=32767,buf+=32767)
186: if(write(file,(char *)buf,32767)!=32767)
187: return(-1L);
188: if(write(file,(char *)buf,(int)count)!=count)
189: return(-1L);
190: return(bytes);
191: }
192: #endif
193:
194: /****************************************************************************/
195: /* Truncates white-space chars off end of 'str' and terminates at first tab */
196: /****************************************************************************/
197: void truncsp(char *str)
198: {
199: uint c;
200:
201: str[strcspn(str,"\t")]=0;
202: c=strlen(str);
203: while(c && (uchar)str[c-1]<=SP) c--;
204: str[c]=0;
205: }
206:
207: /****************************************************************************/
208: /* Puts a backslash on path strings */
209: /****************************************************************************/
210: void backslash(char *str)
211: {
212: int i;
213:
214: i=strlen(str);
215: if(i && str[i-1]!='\\') {
216: str[i]='\\'; str[i+1]=0; }
217: }
218:
219: /****************************************************************************/
220: /* Puts a backslash on path strings if not just a drive letter and colon */
221: /****************************************************************************/
222: void backslashcolon(char *str)
223: {
224: int i;
225:
226: i=strlen(str);
227: if(i && str[i-1]!='\\' && str[i-1]!=':') {
228: str[i]='\\'; str[i+1]=0; }
229: }
230:
231: /****************************************************************************/
232: /* Updates 16-bit "rcrc" with character 'ch' */
233: /****************************************************************************/
234: void ucrc16(uchar ch, ushort *rcrc) {
235: ushort i, cy;
236: uchar nch=ch;
237:
238: for (i=0; i<8; i++) {
239: cy=*rcrc & 0x8000;
240: *rcrc<<=1;
241: if (nch & 0x80) *rcrc |= 1;
242: nch<<=1;
243: if (cy) *rcrc ^= 0x1021; }
244: }
245:
246: /****************************************************************************/
247: /* Returns CRC-16 of string (not including terminating NULL) */
248: /****************************************************************************/
249: ushort crc16(char *str)
250: {
251: int i=0;
252: ushort crc=0;
253:
254: ucrc16(0,&crc);
255: while(str[i])
256: ucrc16(str[i++],&crc);
257: ucrc16(0,&crc);
258: ucrc16(0,&crc);
259: return(crc);
260: }
261:
262: /****************************************************************************/
263: /* Returns CRC-32 of string (not including terminating NULL) */
264: /****************************************************************************/
265: ulong crc32(char *buf, ulong len)
266: {
267: ulong l,crc=0xffffffff;
268:
269: for(l=0;l<len;l++)
270: crc=ucrc32(buf[l],crc);
271: return(~crc);
272: }
273:
274: /****************************************************************************/
275: /* Compares pointers to pointers to char. Used in conjuction with qsort() */
276: /****************************************************************************/
277: int pstrcmp(char **str1, char **str2)
278: {
279: return(strcmp(*str1,*str2));
280: }
281:
282: /****************************************************************************/
283: /* Returns the number of characters that are the same between str1 and str2 */
284: /****************************************************************************/
285: int strsame(char *str1, char *str2)
286: {
287: int i,j=0;
288:
289: for(i=0;i<strlen(str1);i++)
290: if(str1[i]==str2[i]) j++;
291: return(j);
292: }
293:
294: #define MV_BUFLEN 4096
295:
296: /****************************************************************************/
297: /* Moves or copies a file from one dir to another */
298: /* both 'src' and 'dest' must contain full path and filename */
299: /* returns 0 if successful, -1 if error */
300: /****************************************************************************/
301: int mv(char *src, char *dest, char copy)
302: {
303: char str[256],*buf,atr=curatr;
304: int ind,outd;
305: long length,chunk=MV_BUFLEN,l;
306: struct ftime ftime;
307: FILE *inp,*outp;
308:
309: if(!stricmp(src,dest)) /* source and destination are the same! */
310: return(0);
311: if(!fexist(src)) {
312: bprintf("\r\n\7MV ERROR: Source doesn't exist\r\n'%s'\r\n"
313: ,src);
314: return(-1); }
315: if(!copy && fexist(dest)) {
316: bprintf("\r\n\7MV ERROR: Destination already exists\r\n'%s'\r\n"
317: ,dest);
318: return(-1); }
319: if(!copy && ((src[1]!=':' && dest[1]!=':')
320: || (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
321: if(rename(src,dest)) { /* same drive, so move */
322: bprintf("\r\nMV ERROR: Error renaming '%s'"
323: "\r\n to '%s'\r\n\7",src,dest);
324: return(-1); }
325: return(0); }
326: attr(WHITE);
327: if((ind=nopen(src,O_RDONLY))==-1) {
328: errormsg(WHERE,ERR_OPEN,src,O_RDONLY);
329: return(-1); }
330: if((inp=fdopen(ind,"rb"))==NULL) {
331: close(ind);
332: errormsg(WHERE,ERR_FDOPEN,str,O_RDONLY);
333: return(-1); }
334: setvbuf(inp,NULL,_IOFBF,32*1024);
335: if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
336: fclose(inp);
337: errormsg(WHERE,ERR_OPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
338: return(-1); }
339: if((outp=fdopen(outd,"wb"))==NULL) {
340: close(outd);
341: fclose(inp);
342: errormsg(WHERE,ERR_FDOPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
343: return(-1); }
344: setvbuf(outp,NULL,_IOFBF,8*1024);
345: length=filelength(ind);
346: if(!length) {
347: fclose(inp);
348: fclose(outp);
349: errormsg(WHERE,ERR_LEN,src,0);
350: return(-1); }
351: if((buf=(char *)MALLOC(MV_BUFLEN))==NULL) {
352: fclose(inp);
353: fclose(outp);
354: errormsg(WHERE,ERR_ALLOC,nulstr,MV_BUFLEN);
355: return(-1); }
356: l=0L;
357: while(l<length) {
358: bprintf("%2lu%%",l ? (long)(100.0/((float)length/l)) : 0L);
359: if(l+chunk>length)
360: chunk=length-l;
361: if(fread(buf,1,chunk,inp)!=chunk) {
362: FREE(buf);
363: fclose(inp);
364: fclose(outp);
365: errormsg(WHERE,ERR_READ,src,chunk);
366: return(-1); }
367: if(fwrite(buf,1,chunk,outp)!=chunk) {
368: FREE(buf);
369: fclose(inp);
370: fclose(outp);
371: errormsg(WHERE,ERR_WRITE,dest,chunk);
372: return(-1); }
373: l+=chunk;
374: bputs("\b\b\b"); }
375: bputs(" \b\b\b"); /* erase it */
376: attr(atr);
377: getftime(ind,&ftime);
378: setftime(outd,&ftime);
379: FREE(buf);
380: fclose(inp);
381: fclose(outp);
382: if(!copy && remove(src)) {
383: errormsg(WHERE,ERR_REMOVE,src,0);
384: return(-1); }
385: return(0);
386: }
387:
388: /****************************************************************************/
389: /* Prompts user for System Password. Returns 1 if user entered correct PW */
390: /****************************************************************************/
391: char chksyspass(int local)
392: {
393: static int inside;
394: char str[256],str2[256],x,y,atr;
395: int orgcon=console;
396:
397: if(inside) return(0);
398: if(online==ON_REMOTE && !(sys_misc&SM_R_SYSOP))
399: return(0);
400: if(online==ON_LOCAL) {
401: if(!(sys_misc&SM_L_SYSOP))
402: return(0);
403: if(!(node_misc&NM_SYSPW) && !(sys_misc&SM_REQ_PW))
404: return(1); }
405: if(local) {
406: x=lclwx();
407: y=lclwy();
408: atr=lclatr(LIGHTGRAY<<4);
409: STATUSLINE;
410: lclxy(1,node_scrnlen);
411: lputc(CLREOL);
412: lputs(" System Password: "); }
413: else
414: bputs("SY: ");
415: console&=~(CON_R_ECHO|CON_L_ECHO);
416: inside=1;
417: getstr(str,40,K_UPPER);
418: if(local) {
419: TEXTWINDOW;
420: lclatr(atr);
421: lclxy(x,y);
422: statusline(); }
423: inside=0;
424: console=orgcon;
425: if(!local)
426: CRLF;
427: if(strcmp(sys_pass,str)) {
428: sprintf(str2,"%s #%u System password attempt: '%s'"
429: ,useron.alias,useron.number,str);
430: logline("S!",str2);
431: return(0); }
432: return(1);
433: }
434:
435: /****************************************************************************/
436: /* Converts when_t.zone into ASCII format */
437: /****************************************************************************/
438: char *zonestr(short zone)
439: {
440: static char str[32];
441:
442: switch((ushort)zone) {
443: case 0: return("UT");
444: case AST: return("AST");
445: case EST: return("EST");
446: case CST: return("CST");
447: case MST: return("MST");
448: case PST: return("PST");
449: case YST: return("YST");
450: case HST: return("HST");
451: case BST: return("BST");
452: case ADT: return("ADT");
453: case EDT: return("EDT");
454: case CDT: return("CDT");
455: case MDT: return("MDT");
456: case PDT: return("PDT");
457: case YDT: return("YDT");
458: case HDT: return("HDT");
459: case BDT: return("BDT");
460: case MID: return("MID");
461: case VAN: return("VAN");
462: case EDM: return("EDM");
463: case WIN: return("WIN");
464: case BOG: return("BOG");
465: case CAR: return("CAR");
466: case RIO: return("RIO");
467: case FER: return("FER");
468: case AZO: return("AZO");
469: case LON: return("LON");
470: case BER: return("BER");
471: case ATH: return("ATH");
472: case MOS: return("MOS");
473: case DUB: return("DUB");
474: case KAB: return("KAB");
475: case KAR: return("KAR");
476: case BOM: return("BOM");
477: case KAT: return("KAT");
478: case DHA: return("DHA");
479: case BAN: return("BAN");
480: case HON: return("HON");
481: case TOK: return("TOK");
482: case SYD: return("SYD");
483: case NOU: return("NOU");
484: case WEL: return("WEL");
485: }
486:
487: sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
488: return(str);
489: }
490:
491: /****************************************************************************/
492: /* Waits so many seconds. Call with 2 or greater. */
493: /****************************************************************************/
494: void secwait(int sec)
495: {
496: time_t start;
497:
498: start=time(NULL);
499: while(time(NULL)-start<sec)
500: mswait(1);
501: }
502:
503: /****************************************************************************/
504: /* Converts a date string in format MM/DD/YY into unix time format */
505: /****************************************************************************/
506: time_t dstrtounix(char *str)
507: {
508:
509: if(!strncmp(str,"00/00/00",8))
510: return(0);
511: curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
512: if(str[6]<'7')
513: date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
514: else
515: date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
516: if(sys_misc&SM_EURODATE) {
517: date.da_mon=((str[3]&0xf)*10)+(str[4]&0xf);
518: date.da_day=((str[0]&0xf)*10)+(str[1]&0xf); }
519: else {
520: date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
521: date.da_day=((str[3]&0xf)*10)+(str[4]&0xf); }
522: return(dostounix(&date,&curtime));
523: }
524:
525: /****************************************************************************/
526: /* Converts unix time format (long - time_t) into a char str MM/DD/YY */
527: /****************************************************************************/
528: char *unixtodstr(time_t unix, char *str)
529: {
530:
531: if(!unix)
532: strcpy(str,"00/00/00");
533: else {
534: unixtodos(unix,&date,&curtime);
535: if((unsigned)date.da_mon>12) { /* DOS leap year bug */
536: date.da_mon=1;
537: date.da_year++; }
538: if((unsigned)date.da_day>31)
539: date.da_day=1;
540: if(sys_misc&SM_EURODATE)
541: sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
542: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
543: else
544: sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
545: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
546: return(str);
547: }
548:
549: /****************************************************************************/
550: /* Checks the disk drive for the existence of a file. Returns 1 if it */
551: /* exists, 0 if it doesn't. */
552: /****************************************************************************/
553: char fexist(char *filespec)
554: {
555: struct ffblk f;
556:
557: if(findfirst(filespec,&f,0 /*FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0)
558: return(1);
559: return(0);
560: }
561:
562: /****************************************************************************/
563: /* Returns the length of the file in 'filespec' */
564: /****************************************************************************/
565: long flength(char *filespec)
566: {
567: struct ffblk f;
568:
569: if(findfirst(filespec,&f,0)==0)
570: return(f.ff_fsize);
571: return(-1L);
572: }
573:
574: time_t ftimetounix(struct ftime ft)
575: {
576: struct date da;
577: struct time ti;
578:
579: ti.ti_min=ft.ft_min;
580: ti.ti_hour=ft.ft_hour;
581: ti.ti_hund=0;
582: ti.ti_sec=ft.ft_tsec*2;
583: da.da_year=1980+ft.ft_year;
584: da.da_day=ft.ft_day;
585: da.da_mon=ft.ft_month;
586: return(dostounix(&da,&ti));
587: }
588:
589: struct ftime unixtoftime(time_t unix)
590: {
591: struct date da;
592: struct time ti;
593: struct ftime ft;
594:
595: unixtodos(unix,&da,&ti);
596: ft.ft_min=ti.ti_min;
597: ft.ft_hour=ti.ti_hour;
598: ft.ft_tsec=ti.ti_sec/2;
599: ft.ft_year=da.da_year-1980;
600: ft.ft_day=da.da_day;
601: ft.ft_month=da.da_mon;
602: return(ft);
603: }
604:
605: /****************************************************************************/
606: /* Returns the time/date of the file in 'filespec' in time_t (unix) format */
607: /****************************************************************************/
608: long fdate(char *filespec)
609: {
610: int file;
611: struct ftime f;
612: time_t t;
613:
614: if((file=nopen(filespec,O_RDONLY))==-1)
615: return(0);
616: getftime(file,&f);
617: t=ftimetounix(f);
618: close(file);
619: return(t);
620: }
621:
622: long fdate_dir(char *filespec)
623: {
624: struct ffblk f;
625: struct date fd;
626: struct time ft;
627:
628: if(findfirst(filespec,&f,0/* FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0) {
629: fd.da_day=f.ff_fdate&0x1f;
630: fd.da_mon=(f.ff_fdate>>5)&0xf;
631: fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
632: ft.ti_hour=(f.ff_ftime>>11)&0x1f;
633: ft.ti_min=(f.ff_ftime>>5)&0x3f;
634: ft.ti_sec=(f.ff_ftime&0xf)*2;
635: return(dostounix(&fd,&ft)); }
636: else return(0);
637: }
638:
639:
640:
641: /****************************************************************************/
642: /* Returns the FidoNet address kept in str as ASCII. */
643: /****************************************************************************/
644: faddr_t atofaddr(char *str)
645: {
646: char *p;
647: faddr_t addr;
648:
649: addr.zone=addr.net=addr.node=addr.point=0;
650: if((p=strchr(str,':'))!=NULL) {
651: addr.zone=atoi(str);
652: addr.net=atoi(p+1); }
653: else {
654: if(total_faddrs)
655: addr.zone=faddr[0].zone;
656: else
657: addr.zone=1;
658: addr.net=atoi(str); }
659: if(!addr.zone) /* no such thing as zone 0 */
660: addr.zone=1;
661: if((p=strchr(str,'/'))!=NULL)
662: addr.node=atoi(p+1);
663: else {
664: if(total_faddrs)
665: addr.net=faddr[0].net;
666: else
667: addr.net=1;
668: addr.node=atoi(str); }
669: if((p=strchr(str,'.'))!=NULL)
670: addr.point=atoi(p+1);
671: return(addr);
672: }
673:
674: /****************************************************************************/
675: /* Returns an ASCII string for FidoNet address 'addr' */
676: /****************************************************************************/
677: char *faddrtoa(faddr_t addr)
678: {
679: static char str[25];
680: char point[25];
681:
682: sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
683: if(addr.point) {
684: sprintf(point,".%u",addr.point);
685: strcat(str,point); }
686: return(str);
687: }
688:
689: /****************************************************************************/
690: /* Returns string for 2 digit hex+ numbers up to 575 */
691: /****************************************************************************/
692: char *hexplus(uint num, char *str)
693: {
694: sprintf(str,"%03x",num);
695: str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
696: str[1]=str[2];
697: str[2]=0;
698: return(str);
699: }
700:
701: uint hptoi(char *str)
702: {
703: char tmp[128];
704: uint i;
705:
706: if(!str[1] || toupper(str[0])<='F')
707: return(ahtoul(str));
708: strcpy(tmp,str);
709: tmp[0]='F';
710: i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
711: return(i);
712: }
713:
714: #ifndef __FLAT__
715:
716: void beep(int freq, int dur)
717: {
718: sound(freq);
719: mswait(dur);
720: nosound();
721: }
722:
723: int kbd_state(void)
724: {
725: return(peekb(0,0x417)); /* Check scroll lock */
726: }
727:
728: #elif defined(__WIN32__)
729:
730: void beep(int freq, int dur)
731: {
732: Beep(freq,dur); // Requires WINDOWS.H
733: }
734:
735: void mswait(int ms)
736: {
737: Sleep(ms); // Requires WINDOWS.H
738: }
739:
740: #endif
741:
742: #ifdef __OS2__
743:
744: int kbd_state(void)
745: {
746: KBDINFO info;
747:
748: KbdGetStatus(&info,0);
749: return(info.fsState);
750: }
751:
752: void mswait(int msec)
753: {
754: DosSleep(msec ? msec : 1);
755: }
756:
757: #elif defined(__WIN32__)
758:
759: #define KBDSTF_RIGHTSHIFT 0x0001
760: #define KBDSTF_LEFTSHIFT 0x0002
761: #define KBDSTF_CONTROL 0x0004
762: #define KBDSTF_ALT 0x0008
763: #define KBDSTF_SCROLLLOCK_ON 0x0010
764: #define KBDSTF_NUMLOCK_ON 0x0020
765: #define KBDSTF_CAPSLOCK_ON 0x0040
766: #define KBDSTF_INSERT_ON 0x0080
767: #define KBDSTF_LEFTCONTROL 0x0100
768: #define KBDSTF_LEFTALT 0x0200
769: #define KBDSTF_RIGHTCONTROL 0x0400
770: #define KBDSTF_RIGHTALT 0x0800
771: #define KBDSTF_SCROLLLOCK 0x1000
772: #define KBDSTF_NUMLOCK 0x2000
773: #define KBDSTF_CAPSLOCK 0x4000
774: #define KBDSTF_SYSREQ 0x8000
775:
776: int kbd_state(void)
777: {
778: int i=0;
779: ulong l;
780: INPUT_RECORD rec;
781:
782: PeekConsoleInput(stdin,&rec,1,&l);
783: if(rec.EventType==KEY_EVENT)
784: l=rec.Event.KeyEvent.dwControlKeyState;
785: else if(rec.EventType==MOUSE_EVENT)
786: l=rec.Event.MouseEvent.dwControlKeyState;
787: else
788: return(0);
789:
790: /* Translate Win32 key state to IBM key state */
791:
792: if(l&RIGHT_ALT_PRESSED)
793: i|=KBDSTF_RIGHTALT;
794: if(l&LEFT_ALT_PRESSED)
795: i|=KBDSTF_LEFTALT;
796: if(l&RIGHT_CTRL_PRESSED)
797: i|=KBDSTF_RIGHTCONTROL;
798: if(l&LEFT_CTRL_PRESSED)
799: i|=KBDSTF_LEFTCONTROL;
800: if(l&CAPSLOCK_ON)
801: i|=KBDSTF_CAPSLOCK;
802: if(l&NUMLOCK_ON)
803: i|=KBDSTF_NUMLOCK;
804: if(l&SCROLLLOCK_ON)
805: i|=KBDSTF_SCROLLLOCK;
806: if(l&SHIFT_PRESSED)
807: i|=KBDSTF_LEFTSHIFT;
808:
809: return(i);
810: }
811:
812:
813:
814: #endif
815:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.