|
|
1.1 root 1: /* js_uifc.c */
2:
3: /* Synchronet "uifc" (user interface) object */
4:
1.1.1.2 ! root 5: /* $Id: js_uifc.c,v 1.15 2008/12/09 09:48:48 deuce Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #ifndef JAVASCRIPT
39: #define JAVASCRIPT
40: #endif
41:
42: #include "sbbs.h"
43: #include "uifc.h"
44: #include "ciolib.h"
1.1.1.2 ! root 45: #include "js_request.h"
1.1 root 46:
47: /* Properties */
48: enum {
49: PROP_INITIALIZED /* read-only */
50: ,PROP_MODE
51: ,PROP_CHANGES
52: ,PROP_SAVNUM
53: ,PROP_SCRN_LEN
54: ,PROP_SCRN_WIDTH
55: ,PROP_ESC_DELAY
56: ,PROP_HELPBUF
57: ,PROP_HCOLOR
58: ,PROP_LCOLOR
59: ,PROP_BCOLOR
60: ,PROP_CCOLOR
61: ,PROP_LBCOLOR
62: ,PROP_LIST_HEIGHT
63: };
64:
65: static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
66: {
67: jsint tiny;
68: uifcapi_t* uifc;
69:
70: if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
71: return(JS_FALSE);
72:
73: tiny = JSVAL_TO_INT(id);
74:
75: switch(tiny) {
76: case PROP_INITIALIZED:
77: *vp=BOOLEAN_TO_JSVAL(uifc->initialized);
78: break;
79: case PROP_MODE:
80: JS_NewNumberValue(cx,uifc->mode,vp);
81: break;
82: case PROP_CHANGES:
83: *vp=BOOLEAN_TO_JSVAL(uifc->changes);
84: break;
85: case PROP_SAVNUM:
86: *vp=INT_TO_JSVAL(uifc->savnum);
87: break;
88: case PROP_SCRN_LEN:
89: *vp=INT_TO_JSVAL(uifc->scrn_len);
90: break;
91: case PROP_SCRN_WIDTH:
92: *vp=INT_TO_JSVAL(uifc->scrn_width);
93: break;
94: case PROP_ESC_DELAY:
95: *vp=INT_TO_JSVAL(uifc->esc_delay);
96: break;
97: case PROP_HELPBUF:
98: *vp=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,uifc->helpbuf));
99: break;
100: case PROP_HCOLOR:
101: *vp=INT_TO_JSVAL(uifc->hclr);
102: break;
103: case PROP_LCOLOR:
104: *vp=INT_TO_JSVAL(uifc->lclr);
105: break;
106: case PROP_BCOLOR:
107: *vp=INT_TO_JSVAL(uifc->bclr);
108: break;
109: case PROP_CCOLOR:
110: *vp=INT_TO_JSVAL(uifc->cclr);
111: break;
112: case PROP_LBCOLOR:
113: *vp=INT_TO_JSVAL(uifc->lbclr);
114: break;
115: case PROP_LIST_HEIGHT:
116: *vp=INT_TO_JSVAL(uifc->list_height);
117: break;
118: }
119:
120: return(JS_TRUE);
121: }
122:
123: static JSBool js_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
124: {
125: jsint tiny;
126: int32 i=0;
127: uifcapi_t* uifc;
128:
129: if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
130: return(JS_FALSE);
131:
132: tiny = JSVAL_TO_INT(id);
133:
134: switch(tiny) {
135: case PROP_MODE:
136: JS_ValueToInt32(cx, *vp, (int32*)&uifc->mode);
137: break;
138: case PROP_CHANGES:
139: JS_ValueToBoolean(cx,*vp,&uifc->changes);
140: break;
141: case PROP_SAVNUM:
142: JS_ValueToInt32(cx, *vp, (int32*)&uifc->savnum);
143: break;
144: case PROP_SCRN_LEN:
145: JS_ValueToInt32(cx, *vp, (int32*)&uifc->scrn_len);
146: break;
147: case PROP_SCRN_WIDTH:
148: JS_ValueToInt32(cx, *vp, (int32*)&uifc->scrn_width);
149: break;
150: case PROP_ESC_DELAY:
151: JS_ValueToInt32(cx, *vp, (int32*)&uifc->esc_delay);
152: break;
153: case PROP_HELPBUF:
154: uifc->helpbuf=js_ValueToStringBytes(cx, *vp, NULL);
155: break;
156: case PROP_LIST_HEIGHT:
157: JS_ValueToInt32(cx, *vp, (int32*)&uifc->list_height);
158: break;
159: case PROP_HCOLOR:
160: case PROP_LCOLOR:
161: case PROP_BCOLOR:
162: case PROP_CCOLOR:
163: case PROP_LBCOLOR:
164: JS_ValueToInt32(cx, *vp, &i);
165: switch(tiny) {
166: case PROP_HCOLOR:
167: uifc->hclr=(char)i;
168: break;
169: case PROP_LCOLOR:
170: uifc->lclr=(char)i;
171: break;
172: case PROP_BCOLOR:
173: uifc->bclr=(char)i;
174: break;
175: case PROP_CCOLOR:
176: uifc->cclr=(char)i;
177: break;
178: case PROP_LBCOLOR:
179: uifc->lbclr=(char)i;
180: break;
181: }
182: break;
183: }
184:
185: return(JS_TRUE);
186: }
187:
188: static jsSyncPropertySpec js_properties[] = {
189: /* name, tinyid, flags, ver */
190:
191: { "initialized", PROP_INITIALIZED, JSPROP_ENUMERATE|JSPROP_READONLY, 314 },
192: { "mode", PROP_MODE, JSPROP_ENUMERATE, 314 },
193: { "changes", PROP_CHANGES, JSPROP_ENUMERATE, 314 },
194: { "save_num", PROP_SAVNUM, JSPROP_ENUMERATE, 314 },
195: { "screen_length", PROP_SCRN_LEN, JSPROP_ENUMERATE, 314 },
196: { "screen_width", PROP_SCRN_WIDTH, JSPROP_ENUMERATE, 314 },
197: { "list_height", PROP_LIST_HEIGHT, JSPROP_ENUMERATE, 314 },
198: { "esc_delay", PROP_ESC_DELAY, JSPROP_ENUMERATE, 314 },
199: { "help_text", PROP_HELPBUF, JSPROP_ENUMERATE, 314 },
200: { "background_color", PROP_BCOLOR, JSPROP_ENUMERATE, 314 },
201: { "frame_color", PROP_HCOLOR, JSPROP_ENUMERATE, 314 },
202: { "text_color", PROP_LCOLOR, JSPROP_ENUMERATE, 314 },
203: { "inverse_color", PROP_CCOLOR, JSPROP_ENUMERATE, 314 },
204: { "lightbar_color", PROP_LBCOLOR, JSPROP_ENUMERATE, 314 },
205: {0}
206: };
207:
208: /* Convenience functions */
209: static uifcapi_t* get_uifc(JSContext *cx, JSObject *obj)
210: {
211: uifcapi_t* uifc;
212:
213: if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
214: return(NULL);
215:
216: if(!uifc->initialized) {
217: JS_ReportError(cx,"UIFC not initialized");
218: return(NULL);
219: }
220:
221: return(uifc);
222: }
223:
224: /* Methods */
225:
226: static JSBool
227: js_uifc_init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
228: {
229: int ciolib_mode=CIOLIB_MODE_AUTO;
230: char* title="Synchronet";
231: char* mode;
232: uifcapi_t* uifc;
1.1.1.2 ! root 233: jsrefcount rc;
1.1 root 234:
235: *rval = JSVAL_FALSE;
236:
237: if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
238: return(JS_FALSE);
239:
240: if(argc && (title=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
241: return(JS_FALSE);
242:
243: if(argc>1 && (mode=js_ValueToStringBytes(cx, argv[1], NULL))!=NULL) {
244: if(!stricmp(mode,"STDIO"))
245: ciolib_mode=-1;
246: else if(!stricmp(mode,"AUTO"))
247: ciolib_mode=CIOLIB_MODE_AUTO;
248: else if(!stricmp(mode,"X"))
249: ciolib_mode=CIOLIB_MODE_X;
250: else if(!stricmp(mode,"ANSI"))
251: ciolib_mode=CIOLIB_MODE_ANSI;
252: else if(!stricmp(mode,"CONIO"))
253: ciolib_mode=CIOLIB_MODE_CONIO;
254: }
255:
1.1.1.2 ! root 256: rc=JS_SUSPENDREQUEST(cx);
1.1 root 257: if(ciolib_mode==-1) {
1.1.1.2 ! root 258: if(uifcinix(uifc)) {
! 259: JS_RESUMEREQUEST(cx, rc);
1.1 root 260: return(JS_TRUE);
1.1.1.2 ! root 261: }
1.1 root 262: } else {
1.1.1.2 ! root 263: if(initciolib(ciolib_mode)) {
! 264: JS_RESUMEREQUEST(cx, rc);
1.1 root 265: return(JS_TRUE);
1.1.1.2 ! root 266: }
1.1 root 267:
1.1.1.2 ! root 268: if(uifcini32(uifc)) {
! 269: JS_RESUMEREQUEST(cx, rc);
1.1 root 270: return(JS_TRUE);
1.1.1.2 ! root 271: }
1.1 root 272: }
273:
274: *rval = JSVAL_TRUE;
275: uifc->scrn(title);
1.1.1.2 ! root 276: JS_RESUMEREQUEST(cx, rc);
1.1 root 277: return(JS_TRUE);
278: }
279:
280: static JSBool
281: js_uifc_bail(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
282: {
283: uifcapi_t* uifc;
1.1.1.2 ! root 284: jsrefcount rc;
1.1 root 285:
286: if((uifc=get_uifc(cx,obj))==NULL)
287: return(JS_FALSE);
288:
1.1.1.2 ! root 289: rc=JS_SUSPENDREQUEST(cx);
1.1 root 290: uifc->bail();
1.1.1.2 ! root 291: JS_RESUMEREQUEST(cx, rc);
1.1 root 292: return(JS_TRUE);
293: }
294:
295: static JSBool
296: js_uifc_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
297: {
298: char* str;
299: uifcapi_t* uifc;
1.1.1.2 ! root 300: jsrefcount rc;
1.1 root 301:
302: if((uifc=get_uifc(cx,obj))==NULL)
303: return(JS_FALSE);
304:
305: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
306: return(JS_FALSE);
307:
1.1.1.2 ! root 308: rc=JS_SUSPENDREQUEST(cx);
1.1 root 309: uifc->msg(str);
1.1.1.2 ! root 310: JS_RESUMEREQUEST(cx, rc);
1.1 root 311: return(JS_TRUE);
312: }
313:
314: static JSBool
315: js_uifc_pop(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
316: {
317: char* str=NULL;
318: uifcapi_t* uifc;
1.1.1.2 ! root 319: jsrefcount rc;
1.1 root 320:
321: if((uifc=get_uifc(cx,obj))==NULL)
322: return(JS_FALSE);
323:
324: if(argc)
325: str=js_ValueToStringBytes(cx, argv[0], NULL);
326:
1.1.1.2 ! root 327: rc=JS_SUSPENDREQUEST(cx);
1.1 root 328: uifc->pop(str);
1.1.1.2 ! root 329: JS_RESUMEREQUEST(cx, rc);
1.1 root 330: return(JS_TRUE);
331: }
332:
333: static JSBool
334: js_uifc_input(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
335: {
336: char* str;
337: char* org=NULL;
338: char* prompt=NULL;
339: int32 maxlen=0;
340: int32 left=0;
341: int32 top=0;
342: int32 mode=0;
343: int32 kmode=0;
344: uifcapi_t* uifc;
345: uintN argn=0;
1.1.1.2 ! root 346: jsrefcount rc;
1.1 root 347:
348: if((uifc=get_uifc(cx,obj))==NULL)
349: return(JS_FALSE);
350:
351: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
352: && !JS_ValueToInt32(cx,argv[argn++],&mode))
353: return(JS_FALSE);
354: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
355: && !JS_ValueToInt32(cx,argv[argn++],&left))
356: return(JS_FALSE);
357: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
358: && !JS_ValueToInt32(cx,argv[argn++],&top))
359: return(JS_FALSE);
360: if(argn<argc && JSVAL_IS_STRING(argv[argn])
361: && (prompt=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
362: return(JS_FALSE);
363: if(argn<argc && JSVAL_IS_STRING(argv[argn])
364: && (org=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
365: return(JS_FALSE);
366: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
367: && !JS_ValueToInt32(cx,argv[argn++],&maxlen))
368: return(JS_FALSE);
369: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
370: && !JS_ValueToInt32(cx,argv[argn++],&kmode))
371: return(JS_FALSE);
372:
373: if(!maxlen)
374: maxlen=40;
375:
376: if((str=(char*)alloca(maxlen+1))==NULL)
377: return(JS_FALSE);
378:
379: memset(str,0,maxlen+1);
380:
381: if(org)
382: strncpy(str,org,maxlen);
383:
1.1.1.2 ! root 384: rc=JS_SUSPENDREQUEST(cx);
! 385: if(uifc->input(mode, left, top, prompt, str, maxlen, kmode)<0) {
! 386: JS_RESUMEREQUEST(cx, rc);
1.1 root 387: return(JS_TRUE);
1.1.1.2 ! root 388: }
! 389: JS_RESUMEREQUEST(cx, rc);
1.1 root 390:
391: *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,str));
392:
393: return(JS_TRUE);
394: }
395:
396: static JSBool
397: js_uifc_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
398: {
399: char* title=NULL;
400: int32 left=0;
401: int32 top=0;
402: int32 width=0;
403: int32 dflt=0;
404: int32 bar=0;
405: int32 mode=0;
406: JSObject* objarg;
407: uifcapi_t* uifc;
408: uintN argn=0;
409: jsval val;
410: jsuint i;
411: jsuint numopts;
412: str_list_t opts=NULL;
1.1.1.2 ! root 413: jsrefcount rc;
1.1 root 414:
415: if((uifc=get_uifc(cx,obj))==NULL)
416: return(JS_FALSE);
417:
418: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
419: && !JS_ValueToInt32(cx,argv[argn++],&mode))
420: return(JS_FALSE);
421: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
422: && !JS_ValueToInt32(cx,argv[argn++],&left))
423: return(JS_FALSE);
424: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
425: && !JS_ValueToInt32(cx,argv[argn++],&top))
426: return(JS_FALSE);
427: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
428: && !JS_ValueToInt32(cx,argv[argn++],&width))
429: return(JS_FALSE);
430: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
431: && !JS_ValueToInt32(cx,argv[argn++],&dflt))
432: return(JS_FALSE);
433: if(argn<argc && JSVAL_IS_NUMBER(argv[argn])
434: && !JS_ValueToInt32(cx,argv[argn++],&bar))
435: return(JS_FALSE);
436: if(argn<argc && JSVAL_IS_STRING(argv[argn])
437: && (title=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
438: return(JS_FALSE);
439: if(argn<argc && JSVAL_IS_OBJECT(argv[argn])) {
440: if((objarg = JSVAL_TO_OBJECT(argv[argn++]))==NULL)
441: return(JS_FALSE);
442: if(JS_IsArrayObject(cx, objarg)) {
443: if(!JS_GetArrayLength(cx, objarg, &numopts))
444: return(JS_TRUE);
445: opts=strListInit();
446: for(i=0;i<numopts;i++) {
447: if(!JS_GetElement(cx, objarg, i, &val))
448: break;
449: strListPush(&opts,js_ValueToStringBytes(cx,val,NULL));
450: }
451: }
452: }
453:
1.1.1.2 ! root 454: rc=JS_SUSPENDREQUEST(cx);
1.1 root 455: *rval = INT_TO_JSVAL(uifc->list(mode,left,top,width,(int*)&dflt,(int*)&bar,title,opts));
456: strListFree(&opts);
1.1.1.2 ! root 457: JS_RESUMEREQUEST(cx, rc);
1.1 root 458: return(JS_TRUE);
459: }
460:
461: /* Destructor */
462:
463: static void
464: js_finalize(JSContext *cx, JSObject *obj)
465: {
466: uifcapi_t* p;
467:
468: if((p=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
469: return;
470:
471: free(p);
472: JS_SetPrivate(cx,obj,NULL);
473: }
474:
475: static jsSyncMethodSpec js_functions[] = {
476: {"init", js_uifc_init, 1, JSTYPE_BOOLEAN, JSDOCSTR("string title")
477: ,JSDOCSTR("initialize")
478: ,314
479: },
480: {"bail", js_uifc_bail, 0, JSTYPE_VOID, JSDOCSTR("")
481: ,JSDOCSTR("uninitialize")
482: ,314
483: },
484: {"msg", js_uifc_msg, 1, JSTYPE_VOID, JSDOCSTR("string text")
485: ,JSDOCSTR("print a message")
486: ,314
487: },
488: {"pop", js_uifc_pop, 1, JSTYPE_VOID, JSDOCSTR("[string text]")
489: ,JSDOCSTR("popup (or down) a message")
490: ,314
491: },
492: {"input", js_uifc_input, 0, JSTYPE_STRING, JSDOCSTR("[...]")
493: ,JSDOCSTR("prompt for a string input")
494: ,314
495: },
496: {"list", js_uifc_list, 0, JSTYPE_STRING, JSDOCSTR("[...]")
497: ,JSDOCSTR("select from a list of options")
498: ,314
499: },
500: {0}
501: };
502:
1.1.1.2 ! root 503: static JSBool js_uifc_resolve(JSContext *cx, JSObject *obj, jsval id)
! 504: {
! 505: char* name=NULL;
! 506:
! 507: if(id != JSVAL_NULL)
! 508: name=JS_GetStringBytes(JSVAL_TO_STRING(id));
! 509:
! 510: return(js_SyncResolve(cx, obj, name, js_properties, js_functions, NULL, 0));
! 511: }
! 512:
! 513: static JSBool js_uifc_enumerate(JSContext *cx, JSObject *obj)
! 514: {
! 515: return(js_uifc_resolve(cx, obj, JSVAL_NULL));
! 516: }
1.1 root 517:
518: static JSClass js_uifc_class = {
519: "UIFC" /* name */
520: ,JSCLASS_HAS_PRIVATE /* flags */
521: ,JS_PropertyStub /* addProperty */
522: ,JS_PropertyStub /* delProperty */
523: ,js_get /* getProperty */
524: ,js_set /* setProperty */
1.1.1.2 ! root 525: ,js_uifc_enumerate /* enumerate */
! 526: ,js_uifc_resolve /* resolve */
1.1 root 527: ,JS_ConvertStub /* convert */
528: ,js_finalize /* finalize */
529: };
530:
531: JSObject* js_CreateUifcObject(JSContext* cx, JSObject* parent)
532: {
533: JSObject* obj;
534: uifcapi_t* api;
535:
536: if((obj = JS_DefineObject(cx, parent, "uifc", &js_uifc_class, NULL
537: ,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL)
538: return(NULL);
539:
540: if((api=(uifcapi_t*)malloc(sizeof(uifcapi_t)))==NULL)
541: return(NULL);
542:
543: memset(api,0,sizeof(uifcapi_t));
544: api->size=sizeof(uifcapi_t);
545: api->esc_delay=25;
546:
547: if(!JS_SetPrivate(cx, obj, api)) /* Store a pointer to uifcapi_t */
548: return(NULL);
549:
550: return(obj);
551: }
552:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.