/* * mw: use the window subroutines from uw for a MiNT window manager under AES. * * For testing w_output and such, define OTEST; this creates a program that * just echoes keyboard input to the top window, with no MiNT-ness at all. */ #define __OLD_WAY__ /* for evnt_multi() */ #include #include #include #include #include #include #include #include #include "mw.h" /* output from RCS for the resource file names */ #include "mwdefs.h" /* various definitions */ /* for MiNT */ #include #include #define INBUFSIZ 1024 int work_in[11]; int work_out[57]; int pxyarray[20]; int msgbuff[8]; int phys_handle, screen_handle; int ncolors; /* used by ESCb and ESCc */ /* evnt_multi data return spaces */ long dummy; int sdummy; int key; /* * Character stuff (fonts, keymaps). */ FNT *fnttbl[10]; /* List of pointers to fonts avail */ int fontsavail; /* Number of fonts available */ FNT *tempfont; /* font pointer */ int menu_key_map[0x100]; /* menu objects indexed by key map (alt key) read from object file */ int fontmenuobj[] = { /* array of font menu object numbers */ FNT8X8, FNT8X16, FNT6X7, FNTOWN, FNTALT, FNTTNY, FNTOTH, /* Add new font menu items here! */ 0 }; OBJECT *menubar; /* used in startup & finish */ char *caps_table; /* keyboard table for caps-locked keys (sigh) */ /* * globals imported by winsubr */ struct wi_str *wlist; /* a pointer into the window ring */ int scr_x, scr_y, scr_w, scr_h; /* screen workxywh (?) */ FNT *curfont; /* ptr to current font (internal format(?)) */ WIN_MFDB screen_mf; /* mfdb for the screen */ int mouse; /* visibility flag for mouse */ int audibell, visibell; /* what to do on bell */ extern char *getmem(); /* in winsubr.c */ /* * Resource file first/last objects in menu bar. These have to be the first * & last (numerically) which are allowed to have hot-keys assigned to * them. "About ..." is a poor choice since the items after that in the * resource are the space-holders for the accessories. So you can't bind * a key to About... So what? Big deal. */ #define FIRSTOBJ MENUEDIT #define LASTOBJ REFONT /* read a font from a file */ void loadfont (name) char *name; { FNT * curfont; char *tmpfnt; char menustr[20]; char namestr[20]; int shift; unsigned int mask; int i; char *getmem(); if ((curfont = (FNT *) getmem((long)sizeof(FNT))) == NULL) return; i = Fopen(name, 0); if (i<0) return; (void)Fread(i, 2048L, curfont->f_data); (void)Fclose(i); curfont->inc_x = MINMAX(curfont->f_data[16], 1, 8); curfont->inc_y = MINMAX(curfont->f_data[32], 1, 16); curfont->nchars = 128; shift = 8-curfont->inc_x; mask = (1<inc_x)-1; tmpfnt = curfont->f_data; for (i=0; i<2048; i++) { *tmpfnt = (*tmpfnt>>shift)&mask; tmpfnt++; } sscanf(name, "wind%3s", namestr); sprintf(menustr, "%d x %d %s font", curfont->inc_x, curfont->inc_y, namestr); set_menu_string(menustr, fontmenuobj[fontsavail]); fnttbl[fontsavail] = curfont; fontsavail++; return; } void startup() { int i,j; char *tmpfnt; /* start up everything: appl_init, menu, and the like */ appl_init(); if (!rsrc_load("mw.rsc")) { form_alert(1,"[1][Can't find resource file!][ Quit ]"); appl_exit(); exit(0); } rsrc_gaddr(R_TREE, MENUBAR, &menubar); /* * Fill menu_key_map by scanning object strings for ALTINDICATOR. */ for (i = FIRSTOBJ; i <= LASTOBJ; i++) { if (menubar[i].ob_type == G_STRING) { char * found; found = index((char *)menubar[i].ob_spec, ALTINDICATOR); if (found != NULL) { menu_key_map[*(++found)] = i; } } } /* * set caps_table to the base of the table mapping scan codes to * ASCII codes when the CAPS-LOCK key is used. */ caps_table = *(((char **)Keytbl(-1L,-1L,-1L))+2); menu_bar(menubar, 1); /* set mouse symbol to arrow */ graf_mouse(ARROW, NULL); mouse = 1; /* get screen handle and sizes, open virtual workstation */ phys_handle = graf_handle(&sdummy, &sdummy, &sdummy, &sdummy); wind_get(0, WF_WORKXYWH, &scr_x, &scr_y, &scr_w, &scr_h); work_in[0] = Getrez() + 2; for (i=1; i<10; work_in[i++]=1); work_in[10] = 2; screen_handle = phys_handle; v_opnvwk(work_in, &screen_handle, work_out); if (screen_handle == 0) { /* out of handles */ form_alert(1,"[1][Sorry, VDI is out of|workstation handles.][ Quit ]"); appl_exit(); exit(1); } /* set up screen mfdb. Set 'ptr' to NULL and VDI does the rest. */ screen_mf.ptr = NULL; ncolors = work_out[13]; /* * now set up the system fonts */ fontsavail = 0; if ((curfont = (FNT *)getmem((long)sizeof(FNT))) != NULL) { /* GCC specific */ (void)linea0(); tmpfnt = __fonts[1]->dat_table; /* 8 x 8 system font */ for (i=0; i<256; i++) for (j=0; j<8; j++) curfont->f_data[i*16+j] = tmpfnt[i+j*256]; curfont->inc_x = 8; curfont->inc_y = 8; curfont->nchars = 256; set_menu_string("8 x 8 sys font", fontmenuobj[fontsavail]); fnttbl[fontsavail] = curfont; fontsavail++; } if ((curfont = (FNT *)getmem((long)sizeof(FNT))) != NULL) { /* GCC specific */ (void)linea0(); tmpfnt = __fonts[2]->dat_table; /* 8 x 16 system font */ for (i=0; i<256; i++) for (j=0; j<16; j++) curfont->f_data[i*16+j] = tmpfnt[i+j*256]; curfont->inc_x = 8; curfont->inc_y = 16; curfont->nchars = 256; set_menu_string("8 x 16 sys font", fontmenuobj[fontsavail]); fnttbl[fontsavail] = curfont; fontsavail++; } /* set up 6 x 6 system font */ if ((curfont = (FNT *)getmem((long)sizeof(FNT))) != NULL) { /* GCC specific */ (void)linea0(); tmpfnt = __fonts[0]->dat_table; for (i=0; i<256; i++) { int bitpos, index, offset; bitpos = i*6; index = bitpos >> 3; offset = bitpos & ~(~0<<3); for (j=0; j<6; j++) /* for each pixel row in character */ curfont->f_data[i*16+j+1] = ((tmpfnt[index+j*192] << offset) + (tmpfnt[index+j*192+1] >> (8-offset) & ~(~0<>2 & 63; curfont->f_data[i*16+0] = 0; /* extra empty row */ } curfont->inc_x = 6; curfont->inc_y = 7; curfont->nchars = 256; /* * The 6x6 system font can be made better. (dot the i and j.) * This is a bad hack, but it makes it easier to read. */ curfont->f_data[105*16+1] = 8; curfont->f_data[105*16+2] = 0; curfont->f_data[105*16+5] = 8; curfont->f_data[106*16+5] = 20; curfont->f_data[106*16+6] = 8; curfont->f_data[106*16+2] = 0; set_menu_string("6 x 7 sys font", fontmenuobj[fontsavail]); fnttbl[fontsavail] = curfont; fontsavail++; } /* * Load font file(s) if any. */ loadfont("windstd.fnt"); loadfont("windalt.fnt"); loadfont("windtny.fnt"); loadfont("windoth.fnt"); /* * Disable unused font entries. */ for (i = fontsavail; fontmenuobj[i] != 0; i++) { set_menu_string("unavailable font", fontmenuobj[i]); objc_change(menubar, fontmenuobj[i], 0, 0, 0, 0, 0, DISABLED, 0); } } void finish() { /* close all windows and clean up */ if (!mouse) graf_mouse(M_ON,NULL); while (wlist) { #ifndef OTEST if (wlist->pid > 0) (void)Pkill(-wlist->pid,SIGHUP); #endif w_close(wlist); } menu_bar(menubar, 0); v_clsvwk(screen_handle); appl_exit(); exit(0); } #ifndef OTEST /* open a PTY, force a shell to it. Fill in *pfd, *ppid, return 0 or errno */ int get_pipe(shell,pfd,ppid) char *shell; int *pfd; int *ppid; { char pathbuf[80]; int i; int masterfd, slavefd, pid; int oldtty; /* sanity check: does the shell even exist */ if (!shell) return ENOENT; if ((i = Fopen(shell,0)) < 0) return -i; (void)Fclose(i); for (i = 0; i < 999; i++) { sprintf(pathbuf,"q:\\pty.%03d",i); masterfd = Fcreate(pathbuf, 0x04 | 0x02); if (masterfd > 0) { *pfd = masterfd; goto gotpty; } } return EMFILE; /* no pty */ gotpty: slavefd = Fopen(pathbuf,2); if (slavefd < 0) { (void)Fclose(masterfd); return -slavefd; /* can't open PTY twice(?!) */ } if ((oldtty = Fdup(-1)) < 0) { (void)Fclose(masterfd); (void)Fclose(slavefd); return -oldtty; /* can't dup old controlling terminal */ } (void)Fforce(-1,slavefd); (void)Fforce(0,slavefd); (void)Fforce(1,slavefd); (void)Fforce(2,slavefd); pid = Pexec(100,shell,"\0",0L); /* might fail */ (void)Fforce(-1,oldtty); (void)Fforce(0,oldtty); (void)Fforce(1,oldtty); (void)Fforce(2,oldtty); (void)Fclose(slavefd); /* close my copy */ (void)Fclose(oldtty); /* close copy of tty */ *ppid = pid; return (pid < 0 ? -pid : 0); /* return 0 on success */ } #endif /* "fast" controls "window flourish" (grow/shrink boxes) */ int fast = 1; /* * jerky_updates controls whether or not you get an update before each * non-printing character in the output stream. With it on things are * faster; with it off, things are smoother. */ int jerky_updates = 1; /* * mouseflicker controls just that: with it ON, the mouse flickers, but * it is almost always visible: it gets turned off before redraws and * immediately turned on afterwards. With it OFF, the mouse is turned * off before a redraw, then left off until it moves (or you quit or close * the last window). */ int mouseflicker = 1; char alertbuf[40*4+3*9+3]; #ifdef ALARMTEST #define NALARMS 10 static long alarmtimes[NALARMS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; char *dotime(long); char *wkstr(long); #define Waketime(datime) trap_14_wl(47,datime) #define Shutdown() trap_14_w(65) int min_adder = 1; #endif void main(argc,argv) int argc; char *argv[]; { int event; int menuitem = 0; /* Alt sequence mapped to menu item */ int cx, cy, cw, ch; /* temps used for form_center */ int mx, my, mb, mk; /* mouse coordinates from event_multi */ int buttonstate = 2; /* button state to wait for next. */ int clicks; /* number of clicks seen by evnt_multi. */ int cnt; int tmp; OBJECT *obj_tmp; TEDINFO *ted_tmp; struct wi_str *wp, *temp_wp; int sliders = 0; /* set by menu items, arguments to w_open */ int titles = 1; int xsiz, ysiz; int last_x = 80, last_y = 50; /* last size you asked for in SHELLOTH */ /* MiNT stuff */ char *shell; /* name of shell to start in new windows */ char cbuf[INBUFSIZ+1]; extern char *getenv(); int tempfd; int temppid; long readfds, reads; long maxread; int tmppid; long err; audibell = 1; visibell = 1; startup(); /* initialize mouse flicker and flourish checkmarks to default values */ menu_icheck(menubar,MFAST, !fast); menu_icheck(menubar,MSFLICKR, mouseflicker); menu_icheck(menubar,JERKY, jerky_updates); menu_icheck(menubar,AUDIBELL, audibell); menu_icheck(menubar,VISIBELL, visibell); menu_icheck(menubar,TITLES,titles); menu_icheck(menubar,SLIDERS,sliders); /* set curfont to the 8x8 system font and check that menu item */ curfont = fnttbl[0]; objc_change(menubar, FNT8X8, 0, 0, 0, 0, 0, CHECKED, 0); xsiz = 80; ysiz = 25; /* find the name of our shell: the arg, or $SHELL, or MWINIT.PRG */ if (argc > 1) shell = argv[1]; else { shell = getenv("SHELL"); if (!shell) shell = "MWINIT.PRG"; } /* open the first window */ if (w_open(shell, 0, 0, xsiz, ysiz, sliders, titles, curfont)) { /* can't open the window */ exit(0); } /* if get_pipe fails, finish will be called, and we don't want to kill MiNT! */ wlist->pid = 0; #ifndef OTEST /* open the first shell */ if ((err = get_pipe(shell,&tempfd,&temppid))) { sprintf(alertbuf,"[1][Sorry, can't open your shell:|%s][ Quit ]", strerror(err)); form_alert(1,alertbuf); finish(); } /* associate the shell pid, the pipe, and the window */ wlist->fd = tempfd; wlist->pid = temppid; readfds = (1L << tempfd); #endif for (;;) { if (menuitem) { /* * this fork is run when you have faked a menu item with an * ALT key. Wee fall through as if MU_MESAG / MN_SELECTED / * menuitem came back from AES. * * We do not invert any menu titles; below, menu_tnormal * will not be called because msgbuff[3] contains -1. */ event = MU_MESAG; msgbuff[0] = MN_SELECTED; msgbuff[3] = -1; msgbuff[4] = menuitem; menuitem = 0; } else { /* if mouseflicker is ON, "mouse" will never be false */ if (!mouse) { if (!wlist) { /* no windows -- show the mouse */ mouse = 1; graf_mouse(M_ON,NULL); } else { /* get the mouse location so we can wait for it to move */ graf_mkstate(&mx,&my,&sdummy,&sdummy); } } /* this is the main event */ event = MU_MESAG | MU_KEYBD | MU_TIMER | (mouse ? 0 : MU_M1); *(long *)0x003ffffc = 0; event = evnt_multi(event, 2, 2, buttonstate, 1, mx, my, 1, 1, 0, 0, 0, 0, 0, msgbuff, 0, 0, /* use "timer 0" mode */ &mx, &my, &mb, &mk, &key, &clicks); } /* if (event != MU_TIMER) { sprintf(alertbuf,"\r\nEvent: %x (%s%s%s%s%s)\r\n", event, (event & MU_MESAG ? "MESAG " : ""), (event & MU_KEYBD ? "KEYBD " : ""), (event & MU_TIMER ? "TIMER " : ""), (event & MU_BUTTON ? "BUTTON " : ""), (event & MU_M1 ? "M1 " : "")); w_output(wlist,alertbuf,strlen(alertbuf)); } */ if (event & MU_M1) { /* mouse was hidden and moved: show it */ mouse = 1; graf_mouse(M_ON,NULL); } if (event & MU_KEYBD) { /* * Write the key to the pipe of the current window, unless * it's an ALT key that matches a menu item. */ unsigned char keyval = key & 0xff; long keyindex = key >> 8; long keywrite; if (keyval == 0 && (menuitem = menu_key_map[caps_table[keyindex]])) { /* do nothing: setting menuitem is all that's needed. */ } else { if (wlist) { keywrite = (keyindex << 16) | keyval; #ifndef OTEST if (Foutstat(wlist->fd)) (void)Fputchar(wlist->fd,keywrite,0); #else #ifdef ALARMTEST if (keyval == 0x14) { long now = Gettime(); sprintf(alertbuf,"It's %s\r\n",dotime(now)); w_output(wlist,alertbuf,strlen(alertbuf)); } else if (keyval >= '0' && keyval <= '9') { min_adder = keyval - '0'; sprintf(alertbuf,"Adding %d minutes a pop\r\n", min_adder); w_output(wlist,alertbuf,strlen(alertbuf)); } else #endif w_output(wlist,(char *)&keyval,1); #endif /* else ignore the key (process can't accept output) */ } /* else there are no windows, thus nowhere to write to */ } } #ifndef OTEST if (event == MU_TIMER) { /* * We get here only if the ONLY event was a timer event. Read * from pipes; if nothing waiting, Syield(). (note: Fselect * always does at least one Syield, or used to) */ reads = readfds; if (!Fselect(1,&reads,0L,0L)) { /* really no work to do at all */ } else { if (!wlist) { form_alert(1,"[Bomb! Fselect but no windows!][ Ok ]"); finish(); } wp = wlist; do { if (reads & (1L << wp->fd)) { maxread = Finstat(wp->fd); if (maxread > 0) { if (maxread > INBUFSIZ) maxread = INBUFSIZ; maxread = Fread(wp->fd, maxread, cbuf); w_output(wp,(unsigned char *)cbuf,(short)maxread); } else if (maxread < 0) { /* child exited */ (void)Fclose(wp->fd); /* expect it to work */ (void)Pwait3(1,0L); /* kill the zombie */ readfds &= ~(1 << wp->fd); temp_wp = wp; wp = wp->prev; /* goes to wp->next later */ w_close(temp_wp); /* if we just nuked the last window, stop looping */ if (!wlist) break; } else { /* fd maxread is zero (should never happen) */ } } wp = wp->next; } while (wp != wlist); } } #else #ifdef ALARMTEST /* if (event & MU_TIMER) */ { int i; long now; long plus_some_minutes(long t); now = Gettime(); sprintf(alertbuf,"It's %s\r\n",dotime(now)); w_output(wlist,alertbuf,strlen(alertbuf)); for (i=0; ix_chrs; ysiz = wlist->y_chrs; if (!size_dial(&xsiz,&ysiz)) break; tmppid = wlist->pid; if (w_resize(wlist, xsiz, ysiz, wlist->sliders, wlist->titles, 0)) { /* lost the window! Do what we can... */ #ifndef OTEST (void)Pkill(tmppid,SIGHUP); #endif } break; /* "refont" -- reopen the window in the selected font */ case REFONT: if (!wlist) break; tmppid = wlist->pid; if (w_resize(wlist, wlist->x_chrs, wlist->y_chrs, wlist->sliders, wlist->titles, 1)) { /* lost the window! Do what we can... */ #ifndef OTEST (void)Pkill(tmppid,SIGHUP); #endif } break; case FQUIT: finish(); case DABOUT: s_dial(ABOUT, 3); break; case WRENAME: if (!wlist) break; /* no window to rename */ rsrc_gaddr(R_TREE, NEWNAME, &obj_tmp); ted_tmp = (TEDINFO *) obj_tmp[FLD1].ob_spec; strcpy(ted_tmp->te_ptext, wlist->name); form_center(obj_tmp, &cx, &cy, &cw, &ch); form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch); if (!fast) form_dial(FMD_GROW, 0, 0, 20, 10, cx, cy, cw, ch); objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch); tmp = form_do(obj_tmp, FLD1); if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch); form_dial(FMD_FINISH, 0, 0, 20, 10, cx, cy, cw, ch); objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0); if (tmp == OKRENAME) w_rename(wlist, (char *) ted_tmp->te_ptext); break; case JERKY: jerky_updates = !jerky_updates; menu_icheck(menubar,JERKY, jerky_updates); break; case MSFLICKR: mouseflicker = !mouseflicker; menu_icheck(menubar,MSFLICKR, mouseflicker); break; case MFAST: menu_icheck(menubar, MFAST, fast); fast = !fast; break; case FNT8X8: case FNT8X16: case FNT6X7: case FNTOWN: case FNTALT: case FNTTNY: case FNTOTH: /* Add new font menu items here! */ for (cnt = 0; fontmenuobj[cnt] != 0; cnt++) { if (fontmenuobj[cnt] != msgbuff[4]) { /* un-check any font that isn't the new one */ objc_change(menubar, fontmenuobj[cnt], 0, 0, 0, 0, 0, NONE, 0); } else { /* this is the new font: set it & checkmark it */ curfont = fnttbl[cnt]; objc_change(menubar, msgbuff[4], 0, 0, 0, 0, 0, CHECKED, 0); } } break; case AUDIBELL: audibell = !audibell; objc_change(menubar, AUDIBELL, 0, 0, 0, 0, 0, audibell? CHECKED: 0, 0); break; case VISIBELL: visibell = !visibell; objc_change(menubar, VISIBELL, 0, 0, 0, 0, 0, visibell? CHECKED: 0, 0); break; case SHRNKWIN: /* Shrink window to iconic size */ if (wlist) { w_shrink(wlist); } break; case BOTTOMTO: /* send bottom window to top */ w_bottom(); break; case HIDEWIN: /* send top window to bottom */ w_hide(); break; case OSIZEWIN: if (wlist) { w_full(wlist); } break; case SLIDERS: /* toggle sliders for new windows */ sliders = !sliders; menu_icheck(menubar, SLIDERS, sliders); break; case TITLES: /* enable/disable window headers */ titles = !titles; menu_icheck(menubar, TITLES, titles); break; case SETGADG: { /* set gadgets based on settings */ tmppid = wlist->pid; if (w_resize(wlist, wlist->x_chrs, wlist->y_chrs, sliders, titles, 0)) { /* list the window! */ #ifndef OTEST (void)Pkill(tmppid,SIGHUP); #endif } /* make this the "main" style for this window */ wlist->wi_mainstyle = wlist->wi_style; break; } case GADGETS: { /* toggle gadgets for this window */ int tmpslide, tmptitle; if (!wlist) break; /* * If your original ("main") style includes all sliders, * this toggles between all and nothing. Otherwise, * it toggles between your "main" style and everything. */ if (wlist->wi_mainstyle == (WI_WITHSLD|WI_WITHTITLE)) { /* main style is full style */ if (wlist->wi_style == wlist->wi_mainstyle) { /* already all, so make it none */ tmpslide = 0; tmptitle = 0; } else { tmpslide = 1; tmptitle = 1; } } else if (wlist->wi_style != wlist->wi_mainstyle) { /* reset back to mainstyle */ tmpslide = (wlist->wi_mainstyle & WI_WITHSLD); tmptitle = (wlist->wi_mainstyle & WI_WITHTITLE); } else { /* add sliders and title bar */ tmpslide = 1; tmptitle = 1; } tmppid = wlist->pid; if (w_resize(wlist, wlist->x_chrs, wlist->y_chrs, tmpslide, tmptitle, 0)) { /* lost the window! Do what we can... */ #ifndef OTEST (void)Pkill(tmppid,SIGHUP); #endif } break; } case CLOSE: if (!wlist) break; #ifndef OTEST (void)Pkill(-wlist->pid,SIGHUP); #endif break; case SETOTHER: /* set the "other" size */ size_dial(&last_x,&last_y); break; case NEWWIND: /* new window 25x80*/ case NEWOTHER: /* new other */ if (msgbuff[4] == NEWWIND) { /* default window size */ xsiz = 80; ysiz = 25; } else if (msgbuff[4] == NEWOTHER) { xsiz = last_x; ysiz = last_y; } if (!w_open(shell, 0, 0, xsiz, ysiz, sliders, titles, curfont)) { /* create a shell and a pipe */ #ifndef OTEST if ((err = get_pipe(shell,&tempfd,&temppid))) { sprintf(alertbuf, "[1][ Sorry, can't open your shell: |" " %s ][ Cancel ]",strerror(err)); form_alert(1,alertbuf); w_close(wlist); } else { wlist->fd = tempfd; wlist->pid = temppid; readfds |= (1L << tempfd); } #endif } break; } if (msgbuff[3] != -1) menu_tnormal(menubar, msgbuff[3], 1); break; case WM_NEWTOP: /* one of my windows is newly the top window */ /* I don't happen to care... Do I? */ break; case WM_TOPPED: if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_top(wp); break; } wp = wp->next; } while (wp != wlist); break; case WM_SIZED: case WM_MOVED: if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_move(wp, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]); break; } wp = wp->next; } while (wp != wlist); break; case WM_CLOSED: /* kill the process; the window will close when he's dead */ if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { #ifndef OTEST (void)Pkill(-wp->pid,SIGHUP); #endif break; } wp = wp->next; } while (wp != wlist); break; case WM_REDRAW: { if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_redraw(wp,FM_COPY, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]); break; } wp = wp->next; } while (wp != wlist); break; } case WM_FULLED: if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_full(wp); break; } wp = wp->next; } while (wp != wlist); break; case WM_ARROWED: if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_arrow(wp,msgbuff[4]); break; } wp = wp->next; } while (wp != wlist); break; case WM_HSLID: case WM_VSLID: if (!wlist) break; wp = wlist; do { if (wp->aes_handle == msgbuff[3]) { w_slide(wp, msgbuff[0] == WM_HSLID, msgbuff[4]); break; } wp = wp->next; } while (wp != wlist); break; } } } } /* * s_dial performs a simple dialog with buttons and text only. * The index of the terminating button is returned. * If action == 1, the dialog is displayed. If action == 2, it is * removed. If action == 3, both operations are done and form_do is * called. */ int s_dial(tree, action) int tree, action; { int tmp = 0; int cx, cy, cw, ch; OBJECT *obj_tmp; rsrc_gaddr(R_TREE, tree, &obj_tmp); form_center(obj_tmp, &cx, &cy, &cw, &ch); if (action & 1) { form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch); if (!fast) form_dial(FMD_GROW, 0, 0, 20, 10, cx, cy, cw, ch); objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch); } if (action == 3) { tmp = form_do(obj_tmp, 0); } if (action & 2) { if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch); form_dial(FMD_FINISH, 0, 0, 20, 10, cx, cy, cw, ch); objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0); } return (tmp); } /* * set_menu_string sets the menu string for the specified menu object to * newstr. */ void set_menu_string(newstr, object) register char * newstr; int object; { register char * oldstr; oldstr = (char *) menubar[object].ob_spec + 2; while (*oldstr && *newstr) *oldstr++ = *newstr++; if (*oldstr) *oldstr = ' '; } int size_dial(pxsiz,pysiz) int *pxsiz; int *pysiz; { /* * Enter rows and columns dialog */ int cx, cy, cw, ch; int xsiz = *pxsiz; int ysiz = *pysiz; char *rowstr, *colstr; int tmp; OBJECT *obj_tmp; TEDINFO *ted_tmp; /* show the mouse if it's hidden */ /* if mouseflicker is ON, "mouse" will never be false. */ if (!mouse) { mouse = 1; graf_mouse(M_ON,NULL); } rsrc_gaddr(R_TREE, WINDSIZE, &obj_tmp); ted_tmp = (TEDINFO *) obj_tmp[WINDROWS].ob_spec; rowstr = ((char *)ted_tmp->te_ptext); if (ysiz < 2) ysiz = 2; if (xsiz < 2) xsiz = 2; if (ysiz > 99) ysiz = 99; if (xsiz > 300) xsiz = 300; ted_tmp = (TEDINFO *) obj_tmp[WINDCOLS].ob_spec; colstr = ((char *)ted_tmp->te_ptext); sprintf(rowstr,"%02d",ysiz); sprintf(colstr,"%03d",xsiz); form_center(obj_tmp, &cx, &cy, &cw, &ch); form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch); if (!fast) form_dial(FMD_GROW, 0, 0, 20, 10, cx, cy, cw, ch); objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch); tmp = form_do(obj_tmp, WINDROWS); if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch); form_dial(FMD_FINISH, 0, 0, 20, 10, cx, cy, cw, ch); objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0); if (tmp == WINDCANC) return(FALSE); xsiz = xatoi(colstr); ysiz = xatoi(rowstr); if (xsiz < 10) xsiz = 10; if (xsiz > 300) xsiz = 300; if (ysiz < 2) ysiz = 2; if (ysiz > 99) ysiz = 99; *pxsiz = xsiz; *pysiz = ysiz; return (TRUE); } int xatoi(s) char *s; { int result = 0; char c; while (c = *s++) { if (c >= '0' && c <= '9') { result *= 10; result += (c - '0'); } else return result; } return result; } void do_editkeys() { /* * Enter function-key-edit dialog */ int cx, cy, cw, ch; char *namestr, *keystr; int tmp; OBJECT *obj_tmp; TEDINFO *ted_tmp; int cycle, direction; char *found; /* show the mouse if it's hidden */ /* if mouseflicker is ON, "mouse" will never be false. */ if (!mouse) { mouse = 1; graf_mouse(M_ON,NULL); } rsrc_gaddr(R_TREE, EDITKEYS, &obj_tmp); ted_tmp = (TEDINFO *) obj_tmp[ITEMNAME].ob_spec; namestr = ((char *)ted_tmp->te_ptext); ted_tmp = (TEDINFO *) obj_tmp[ITEMKEY].ob_spec; keystr = ((char *)ted_tmp->te_ptext); for (cycle = FIRSTOBJ; cycle <= LASTOBJ; cycle++) { /* if it's a string & it doesn't start with dash... */ if (menubar[cycle].ob_type == G_STRING && *(char *)menubar[cycle].ob_spec != '-') break; } if (cycle > LASTOBJ) return; /* no strings in the menu?! */ strncpy(namestr,(char *)menubar[cycle].ob_spec,20); if (found = index((char *)menubar[cycle].ob_spec, ALTINDICATOR)) { *keystr = *(found+1); } else *keystr = ' '; form_center(obj_tmp, &cx, &cy, &cw, &ch); form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch); if (!fast) form_dial(FMD_GROW, 0, 0, 20, 10, cx, cy, cw, ch); objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch); while (1) { /* tmp comes back with hi bit set to indicate double-clicks */ tmp = (form_do(obj_tmp, ITEMKEY) & 0x7fff); /* (do this regardless of what button you used to get out) */ /* see if you changed the one you were looking at */ if (found && *(found+1) != *keystr) { /* Had a def'n and you changed it. */ /* un-set the old meaning */ menu_key_map[*(found+1)] = 0; if (!*keystr || *keystr == ' ') { /* changed to nothing */ *found = ' '; *(found+1) = ' '; } else { /* changed to something */ *(found+1) = *keystr; menu_key_map[*keystr] = cycle; } } else if (!found && *keystr && *keystr != ' ') { /* didn't have a def'n and you gave one */ menu_key_map[*keystr] = cycle; for (found = (char *)menubar[cycle].ob_spec; *found; found++) ; *(--found) = *keystr; *(--found) = ALTINDICATOR; } /* else you didn't change it */ if (tmp != ITEMOK) { direction = (tmp == ITEMNEXT ? 1 : -1); for (cycle += direction; cycle <= LASTOBJ && cycle >= FIRSTOBJ; cycle += direction) { if (menubar[cycle].ob_type == G_STRING && *(char *)menubar[cycle].ob_spec != '-') break; } if (cycle > LASTOBJ) cycle = FIRSTOBJ; else if (cycle < FIRSTOBJ) cycle = LASTOBJ; strncpy(namestr,(char *)menubar[cycle].ob_spec,20); if (found = index((char *)menubar[cycle].ob_spec, ALTINDICATOR)) { *keystr = *(found+1); } else *keystr = ' '; /* de-select the "next" button, redraw */ /* should clip the redraw to the parts that matter */ objc_change(obj_tmp,ITEMNEXT,0,cx,cy,cw,ch,NORMAL,0); objc_draw(obj_tmp,0,5,cx,cy,cw,ch); } else break; } if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch); form_dial(FMD_FINISH, 0, 0, 20, 10, cx, cy, cw, ch); objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0); return; } #ifdef ALARMTEST check_ram() { static unsigned long *buf = 0; static long size; static int num_errors = 0; unsigned long i; if (!buf) { size = (Malloc(-1L)/4) *4; buf = (unsigned long *)Malloc(size); for (i=0; i<(size/4); i++) buf[i] = i; } else { for (i=0; i<(size/4); i++) { if (buf[i] != i) { num_errors++; /* re-init the buffer */ for (i=0; i<(size/4); i++) buf[i] = i; break; } } sprintf(alertbuf,"%d errors so far\r\n",num_errors); w_output(wlist,alertbuf,strlen(alertbuf)); } } char *wkstrs[] = { "You won", "In the past", "You don't win", "Time zeroed as you asked", "First of that month", "This time tomorrow" }; char *wkstr(long v) { if (v < 0 || v > 4) return "Unknown"; else return wkstrs[v]; } /* * advance a time by one minute. BUT - don't include seconds. * Since we aren't including seconds, we round the input to the * NEAREST minute (not just rounding down). */ long plus_some_minutes(long t) { long month = ((t >> 21) & 0xf); long day = ((t >> 16) & 0x1f); long year = ((t >> 25) & 0x7f); long hour = ((t >> 11) & 0x1f); long minute = ((t >> 5) & 0x3f); long second = ((t & 0x1f) << 1); if (second >= 30) minute += 1; second = 0; minute += min_adder; if (minute >= 60) { minute -= 60; hour += 1; if (hour >= 24) { hour -= 24; day += 1; } } return ((year << 25) | (month << 21) | (day << 16) | (hour << 11) | (minute << 5) | (second >> 1)); } /* * return a printable string for a datime value */ char *dotime(long t) { static char tbuf[18]; sprintf(tbuf,"%02ld/%02ld/%02ld %02ld:%02ld:%02ld", ((t >> 21) & 0xf), ((t >> 16) & 0x1f), ((t >> 25) & 0x7f) + 80, ((t >> 11) & 0x1f), ((t >> 5) & 0x3f), ((t & 0x1f) << 1)); /* sprintf(alertbuf,"dotime(%lx) -> %s\r\n",t,tbuf); w_output(wlist,alertbuf,strlen(alertbuf)); */ return tbuf; } long untime(char *s) { long year, month, day, hour, minute, second; long t; #define twodigits(s) (((*(s) - '0') * 10) + (*((s)+1) - '0')) month = twodigits(s); day = twodigits(s+2); year = twodigits(s+4) - 80; hour = twodigits(s+6); minute = twodigits(s+8); second = twodigits(s+10); t = (year << 25) | (month << 21) | (day << 16) | (hour << 11) | (minute << 5) | (second >> 1); /* sprintf(alertbuf,"untime %s -> %lx\r\n",s,t); w_output(wlist,alertbuf,strlen(alertbuf)); */ return t; } /* * do the alarm dialog box */ do_alarm() { int cx, cy, cw, ch; OBJECT *obj_tmp; TEDINFO *ted_tmp; char *alstr, *numstr; int cycle; int tmp; int direction; if (!mouse) { mouse = 1; graf_mouse(M_ON, NULL); } rsrc_gaddr(R_TREE, TALARM, &obj_tmp); ted_tmp = (TEDINFO *) obj_tmp[ALRMTIME].ob_spec; alstr = ((char *)ted_tmp->te_ptext); ted_tmp = (TEDINFO *) obj_tmp[ALRMNUM].ob_spec; numstr = ((char *)ted_tmp->te_ptext); form_center(obj_tmp, &cx, &cy, &cw, &ch); form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch); /* objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch); */ cycle = 0; while (1) { sprintf(numstr,"%d",cycle); if (alarmtimes[cycle] == -1) { *alstr = '\0'; } else { char *p, *tmpstr = dotime(alarmtimes[cycle]); /* funky strcpy with no punctuation */ for (p = alstr; *tmpstr; ) { *p++ = *tmpstr++; *p++ = *tmpstr++; tmpstr++; } *p = '\0'; } objc_draw(obj_tmp,0,5,cx,cy,cw,ch); tmp = (form_do(obj_tmp,ALRMTIME) & 0x7f); /* regardless of what button you used to get out... */ if (*alstr) { /* w_output(wlist,alstr,strlen(alstr)); */ alarmtimes[cycle] = untime(alstr); /* truncate seconds down to zero */ alarmtimes[cycle] &= ~0x1f; } else alarmtimes[cycle] = -1; /* you cleared it */ if (tmp != ALRMOK) { direction = (tmp == ALRMNEXT ? 1 : -1); cycle += direction; if (cycle < 0) cycle = 0; if (cycle >= NALARMS) cycle = NALARMS-1; /* de-select the "next" button, redraw */ objc_change(obj_tmp,ITEMNEXT,0,cx,cy,cw,ch,NORMAL,0); } else break; /* you exited with "OK" */ } form_dial(FMD_FINISH,0,0,20,10,cx,cy,cw,ch); objc_change(obj_tmp,tmp,0,cx,cy,cw,ch,NONE,0); return(TRUE); } #endif