/* * The GEM stuff. */ static char rcsid[] = "$Id: gem.c,v 1.15 1993/06/06 23:22:04 mike Exp $"; /* $Log: gem.c,v $ * Revision 1.15 1993/06/06 23:22:04 mike * - Fixed bug: Cursor positioning with the mouse now also works when * the left margin > 0. * * Revision 1.14 1993/06/06 22:45:20 mike * - The volatile declaration for `pch' is not needed anymore, the new version * (2.4.2) of gcc does not generate wrong code if its missing. * * Revision 1.13 1992/12/30 03:06:08 mike * - Made variable `pch' in function `exec_gem' volatile. This fixes * a bug in the `Dsetpath' binding (or in gcc?), a long story... * * Revision 1.12 1992/11/29 01:16:58 mike * - The cursor is gets redrawn correctely now after a `window moved' * message. * - Fixed an error in the routine to select a new font size. * * Revision 1.11 1992/11/18 23:20:12 mike * - include stio.h to get some more declarations. * * Revision 1.10 1992/11/13 18:35:04 mike * - Fixed bug: `new_font' should work correctely now in case the request * for a new font size is rejected. * * Revision 1.9 1992/11/10 23:50:38 mike * - Call `quit' with some other parameters. * * Revision 1.8 1992/11/10 21:50:08 mike * - Changed some declarations. * - Gobbles the first redraw message we ever get. This is to avoid * a superfluous redraw message after opening the text window. * * Revision 1.7 1992/11/10 02:21:06 mike * - Some clean ups to prevent warnings from gcc. * * Revision 1.6 1992/11/08 23:09:00 mike * - Lots'a changes. * * Revision 1.5 1992/10/28 15:03:42 mike * - Replaced `toggle_cursor()' by the two functions `Cursor_on()' and * `Cursor_off()'. * - Fixed bug in calculation of the window size for the buffers window. * * Revision 1.4 1992/10/28 00:24:18 mike * - Lots'a changes. * * Revision 1.3 1992/10/12 22:26:04 mike * - Discarded virtual workstation `Vw_clear'. Its job is done by * `Vw_print' now. * * Revision 1.2 1992/10/12 21:20:44 mike * - Lots'a changes ... * * Revision 1.1 1992/10/03 01:32:48 mike * Initial revision * */ #include #include #include #include #include #include #include #include #include #include "gem.h" #include "me2.h" #include "me2rsc.h" #include "stio.h" #define EVENTS (MU_KEYBD | MU_MESAG | MU_BUTTON) extern int abs(int); extern int anycb(); extern int quit(); extern void rc_constrain(); extern void new_window_size(); extern void TOS_mode(); extern void GEM_mode(); extern int file_select(); extern int filesave(); extern int refresh(); extern int MMload(); extern int filevisit_guts(); extern int GEM_filevisit(); extern int spawn_shell(); extern int update(); extern int use_buffer(); extern int next_line(); extern int getgoal(); extern void display_buffer(); extern void use_window(); extern void _lib_unx2dos(); extern void t_beep(); int Phys_handle = -1; /* AES physical screen handle */ int Vw_print; /* Handle of 1st virtual workstation */ int Vw_cursor; /* Handle of 2nd virtual workstation */ int Wchar; /* From the graf_handle() call */ int Hchar; /* From the graf_handle() call */ int Font_size = 10; /* Current font size in pt */ int Wkind; /* Window kind for the text window */ int Text_window = -1; /* Window handle of the text window */ int Deskx,Desky; /* Position of the desktop working area */ int Deskw,Deskh; /* Size of the desktop working area */ int Workx,Worky; /* Position of the window working area */ int Workw,Workh; /* Size of the window working area */ int Fullx,Fully; /* Position of the max. working area */ int Fullw,Fullh; /* Size of the max. working area */ long *Menu_buffer; /* Buffer to hold the menu line */ int Menu_buffer_size; /* # of longwords in `Menu_buffer' */ int Cursor_x,Cursor_y; /* Cursor position (screen coords) */ short Clip_sem = 0; /* Is clipping enabled? */ char MC2[128]; /* Complete path of MC2 */ char MC2_options[128]; /* Options for MC2 */ char MCO_pathname[NFILEN]; /* Path for *.mco file selector */ char MUT_pathname[NFILEN]; /* Path for *.mut file selector */ int Wait_flag = 0; /* Always wait after MC2 */ char Setup_filename[256] = "me2.inf";/* Name of setup file */ unsigned int TOS_version; /* The TOS version number */ OBJECT *Menu; /* Pointer to the menu tree */ short Buffers_window = -1; /* State of the buffers window */ GEM_window Bw; /* The buffers window */ static int Last_pt_item = RSC_10PT; static short Gobble_arrow_events = 0; void redraw_text_window(); char *pathfind(char *env, char *file, char *sep); /* * Terminate the editor. */ static void terminate() { if (anycb()) { if (form_alert(1, "[2][Warning: Modified buffers exist.|Quit anyway?][Yes|No]") == 2) return; } Cursor_off(); quit(TRUE,0); } /* * Redraw the whole screen including the menu line. * * Set the mouse pointer to arrow form and reset the mouse-hidden-counter. */ void redraw_screen() { register int lwords; register long *buffer; register long *ptr; buffer = Menu_buffer; lwords = Menu_buffer_size; ptr = (long *) Physbase(); while (lwords--) *ptr++ = *buffer++; form_dial(FMD_FINISH,0,0,0,0,Deskx,Desky,Deskw,Deskh); graf_mouse(ARROW,NULL); v_show_c(Phys_handle,0); } /* * Display the about box and wait for the `Ok' button. */ static void display_about_box() { OBJECT *box; int x,y,w,h; rsrc_gaddr(R_TREE,RSC_ABOUT_BOX,&box); form_center(box,&x,&y,&w,&h); form_dial(FMD_START,0,0,0,0,x,y,w,h); objc_draw(box,ROOT,MAX_DEPTH,x,y,w,h); form_do(box,0); objc_change(box,RSC_OK1,0,x,y,w,h,NORMAL,0); form_dial(FMD_FINISH,0,0,0,0,x,y,w,h); } /* * Save the current setup. */ static void save_setup() { FILE *fd; if ((fd = fopen(Setup_filename,"w")) == NULL) { form_alert(1,"[3][Cannot create|setup file!][Abort]"); return; } graf_mouse(HOURGLASS,NULL); fprintf(fd,"%d\n",Workx); fprintf(fd,"%d\n",Worky); fprintf(fd,"%d\n",Workw); fprintf(fd,"%d\n",Workh); fprintf(fd,"%d\n",Font_size); fprintf(fd,"%d\n",Wait_flag); fprintf(fd,"%s\n",MC2); fprintf(fd,"%s\n",MC2_options); fprintf(fd,"%s\n",MCO_pathname); fprintf(fd,"%s\n",MUT_pathname); fprintf(fd,"%d\n",Buffers_window); fprintf(fd,"%d\n",Bw.wx); fprintf(fd,"%d\n",Bw.wy); fprintf(fd,"%d\n",Bw.ww); fprintf(fd,"%d\n",Bw.wh); fprintf(fd,"%d\n",Gobble_arrow_events); fclose(fd); graf_mouse(ARROW,NULL); } /* * Load the setup file. * * Return value: 1 - Ok, 0 - Error */ int load_setup() { FILE *fd; char *s; int dummy; int n; int x,y,w,h; if ((s = pathfind("PATH",Setup_filename,":")) != NULL) strcpy(Setup_filename,s); MC2[0] = MC2_options[0] = MCO_pathname[0] = '\0'; if ((fd = fopen(Setup_filename,"r")) == NULL) return 0; n = fscanf(fd, "%d\n%d\n%d\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%hd\n%d\n%d\n%d\n%d\n%hd", &Workx,&Worky,&Workw,&Workh,&Font_size,&Wait_flag,MC2, MC2_options,MCO_pathname,MUT_pathname,&Buffers_window, &Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh,&Gobble_arrow_events); fclose(fd); if (n != 16) return 0; if (Workw > Fullw) Workw = Fullw; if (Workh > Fullh) Workh = Fullh; rc_constrain(&Workx,&Worky,Workw,Workh); if (Font_size != 10) { menu_icheck(Menu,RSC_10PT,0); switch (Font_size) { case 8 : menu_icheck(Menu, Last_pt_item = RSC_8PT, 1); break; case 9 : menu_icheck(Menu, Last_pt_item = RSC_9PT, 1); break; case 16 : menu_icheck(Menu, Last_pt_item = RSC_16PT, 1); break; case 18 : menu_icheck(Menu, Last_pt_item = RSC_18PT, 1); break; case 20 : menu_icheck(Menu, Last_pt_item = RSC_20PT, 1); } vst_point(Vw_print,Font_size,&dummy,&dummy,&Wchar,&Hchar); } wind_calc(WC_BORDER,Bw.wkind,Bw.wx,Bw.wy,Bw.ww,Bw.wh,&x,&y,&w,&h); if (w > Fullw) w = Fullw; if (h > Fullh) h = Fullh; rc_constrain(&x,&y,w,h); wind_calc(WC_WORK,Bw.wkind,x,y,w,h,&Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh); if (Wait_flag) menu_icheck(Menu,RSC_MC2WAIT,1); if (Gobble_arrow_events) menu_icheck(Menu,RSC_GOBBLE,1); return 1; } /* * Process a `window moved' message. */ static void window_moved(window,x,y,w,h) int window; int x,y,w,h; { if (window == Text_window) { rc_constrain(&x,&y,w,h); Cursor_off(); wind_set(window,WF_CURRXYWH,x,y,w,h); wind_calc(WC_WORK,Wkind,x,y,w,h,&x,&y,&Workw,&Workh); Cursor_x -= Workx - x; Cursor_y -= Worky - y; Workx = x; Worky = y; Cursor_on(); } else if (window == Bw.whandle) { wind_set(window,WF_CURRXYWH,x,y,w,h); wind_calc(WC_WORK,Bw.wkind,x,y,w,h,&Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh); } } /* * Process a `window sized' message. */ static void window_sized(window,x,y,w,h) int window; int x,y,w,h; { register int i; if (window == Bw.whandle) { wind_set(window,WF_CURRXYWH,x,y,w,h); wind_calc(WC_WORK,Bw.wkind,x,y,w,h,&Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh); i = Bw.wh / Bw.hchar; if (i >= Bw.nlines) i = 1000; else i = (i * 1000) / Bw.nlines; wind_set(Bw.whandle, WF_VSLSIZE, i, 0 ,0, 0); } } /* * Put the text window on top. */ void top_text_window() { if (Text_window > 0) { wind_set(Text_window,WF_TOP,0,0,0,0); if (!Buffers_window) Buffers_window = 0; } } /* * Change to a new font size. */ static void new_font(size,menu_item) int size; int menu_item; { int dummy; int nrow; int ncol; int new_wchar; int new_hchar; top_text_window(); vst_point(Vw_print,size,&dummy,&dummy,&new_wchar,&new_hchar); nrow = Workh / new_hchar; ncol = Workw / new_wchar; if (ncol < 39 || nrow < 6) { form_alert(1,"[3][No way to display at least|39x6 characters with this|font in this window!][Give up]"); vst_point(Vw_print,Font_size,&dummy,&dummy,&dummy,&dummy); return; } Font_size = size; Wchar = new_wchar; Hchar = new_hchar; menu_icheck(Menu,Last_pt_item,0); menu_icheck(Menu,menu_item,1); Last_pt_item = menu_item; new_window_size(nrow,ncol); } /* * Open the buffers window. */ void open_buffers_window() { int x,y,w,h; vsf_interior(Bw.vw_text,0); /* Empty */ vsf_perimeter(Bw.vw_text,0); /* No frame */ vsf_color(Bw.vw_text,0); /* Bg color */ vst_color(Bw.vw_text,1); /* Text in "black" */ vst_alignment(Bw.vw_text,0,3,&x,&x); graf_handle(&Bw.wchar,&Bw.hchar,&x,&x); Bw.font_size = 10; wind_calc(WC_WORK,Bw.wkind,Deskx,Desky,Deskw,Deskh,&Bw.fx,&Bw.fy, &Bw.fw,&Bw.fh); if (Buffers_window < 0) { Bw.wx = Bw.fx; Bw.wy = Bw.fy; Bw.ww = 35 * Bw.wchar; Bw.wh = 20 * Bw.hchar; Bw.y_offset = 0; } if ((Bw.whandle = wind_create(Bw.wkind,Deskx,Desky,Deskw,Deskh)) < 0) { form_alert(1,"[3][No window available!][Abort]"); return; } wind_set(Bw.whandle,WF_NAME," ME2 Buffers "); wind_set(Bw.whandle,WF_INFO,"Flags Buffer File"); wind_calc(WC_BORDER,Bw.wkind,Bw.wx,Bw.wy,Bw.ww,Bw.wh,&x,&y,&w,&h); wind_open(Bw.whandle,x,y,w,h); menu_icheck(Menu, RSC_BUFFWIND, Buffers_window = 1); } /* * Close the buffers window. */ void close_buffers_window() { wind_close(Bw.whandle); wind_delete(Bw.whandle); menu_icheck(Menu, RSC_BUFFWIND, Buffers_window = 0); } /* * Update the buffers window. */ static void update_bw() { register int x,y; register int i; register int n; register char *p; register Buffer *b; Buffer *topline; int pxyarray[4]; char flags[6]; char c1,c2; /* * Clear the working area. */ pxyarray[0] = Bw.wx; pxyarray[1] = Bw.wy; pxyarray[2] = Bw.wx + Bw.ww - 1; pxyarray[3] = Bw.wy + Bw.wh - 1; v_bar(Bw.vw_text,pxyarray); topline = NULL; /* * Count the lines and find the top line of the window. */ for (b = first_buffer, n = 0; b != NULL; n++, b = b->nextb) { if (n == Bw.y_offset) topline = b; } Bw.nlines = n--; /* * Determine the size of the vertical slider. */ i = Bw.wh / Bw.hchar; if (i >= Bw.nlines) { i = 1000; b = first_buffer; Bw.y_offset = 0; } else { i = (i * 1000) / Bw.nlines; b = topline; } wind_set(Bw.whandle, WF_VSLSIZE, i, 0 ,0, 0); /* * Fill the text window. */ if (!Clip_sem) vs_clip(Bw.vw_text,1,pxyarray); x = Bw.wx; y = Bw.wy + Bw.hchar; while (b != NULL) { i = b->b_flags; strcpy(flags,"-----"); if (i & BFNOCARE) flags[0] = '.'; else if (i & BFCHG) flags[0] = 'M'; if (i & BFUNDO) flags[1] = 'u'; if (i & BFHIDDEN) flags[2] = 'H'; if (i & BFINTERACTIVE) flags[3] = 'i'; if (i & BFVIEW) flags[4] = 'V'; v_gtext(Bw.vw_text,x,y,flags); if (i = (b->b_bname.size > 14)) { p = get_dString(b->b_bname); c1 = p[13]; c2 = p[14]; p[19] = '$'; p[20] = '\0'; } v_gtext(Bw.vw_text, x + 6 * Bw.wchar, y, get_dString(b->b_bname)); if (i) { p[13] = c1; p[14] = c2; } v_gtext(Bw.vw_text, x + 20 * Bw.wchar, y, get_dString(b->b_fname)); y += Bw.hchar; b = b->nextb; } /* * Determine the position of the vertical slider. */ i = Bw.nlines - Bw.wh / Bw.hchar; if (i > 0) wind_set(Bw.whandle, WF_VSLIDE, (Bw.y_offset * 1000) / i, 0, 0, 0); if (!Clip_sem) vs_clip(Bw.vw_text,0,pxyarray); } /* * Display a new number in RSC_ROWS or RSC_COLS. */ static void display_number(box,obj,num) OBJECT *box; int obj; int num; { register TEDINFO *ted; ted = (TEDINFO *) box[obj].ob_spec; sprintf(ted->te_ptext,"%3d",num); ted->te_txtlen = strlen(ted->te_ptext); } /* * Display the new window size dialog box. */ static void new_size_dialog() { extern int t_nrow,t_ncol; OBJECT *box; int obj; int rows,cols; int max_rows,max_cols; int x,y,w,h; rsrc_gaddr(R_TREE,RSC_SIZE_BOX,&box); display_number(box, RSC_ROWS, rows = t_nrow + 1); display_number(box, RSC_COLS, cols = t_ncol); max_rows = Fullh / Hchar; max_cols = Fullw / Wchar; form_center(box,&x,&y,&w,&h); form_dial(FMD_START,0,0,0,0,x,y,w,h); objc_draw(box,ROOT,MAX_DEPTH,x,y,w,h); do { obj = form_do(box,0) & 0x7fff; switch (obj) { case RSC_OK2 : new_window_size(rows,cols); /* Fall thru */ case RSC_CANCEL2 : objc_change(box,obj,0,x,y,w,h,NORMAL,1); break; case RSC_ROWS_LESS : if (rows - 1 >= 6) { display_number(box,RSC_ROWS,--rows); objc_draw(box,RSC_ROWS,0,x,y,w,h); } break; case RSC_COLS_LESS : if (cols - 1 >= 39) { display_number(box,RSC_COLS,--cols); objc_draw(box,RSC_COLS,0,x,y,w,h); } break; case RSC_ROWS_MORE : if (rows + 1 <= max_rows) { display_number(box,RSC_ROWS,++rows); objc_draw(box,RSC_ROWS,0,x,y,w,h); } break; case RSC_COLS_MORE : if (cols + 1 <= max_cols) { display_number(box,RSC_COLS,++cols); objc_draw(box,RSC_COLS,0,x,y,w,h); } } } while (obj != RSC_OK2 && obj != RSC_CANCEL2); form_dial(FMD_FINISH,0,0,0,0,x,y,w,h); } /* * Compile MUTT file `fname'. * * Note: `fname' MUST contain a complete path specification * beginnig with :\ * * Return value: The status returned by the Mutt compiler. */ static int compile(fname) char *fname; { register char *p; char command[NFILEN+128]; char current_path[NFILEN]; char ch; char *pch; int current_drive; int status; strcpy(command,MC2); strcat(command," "); strcat(command,MC2_options); strcat(command," "); strcat(command,fname); TOS_mode(); puts(command); Dgetpath(current_path,0); current_drive = Dgetdrv(); Dsetdrv(toupper(fname[0]) - 'A'); if ((pch = strrchr(fname,'\\')) == NULL) pch = strrchr(fname,'/'); ch = *++pch; *pch = '\0'; for (p = fname; *p; p++) { if (*p == '/') *p = '\\'; } Dsetpath(fname + 2); for (p = fname; *p; p++) { if (*p == '\\') *p = '/'; } *pch = ch; status = system(command); Dsetdrv(current_drive); Dsetpath(current_path); if (Wait_flag || status) { printf("Return status: %d\n",status); puts("[Hit Return to resume editing]"); Cconin(); } GEM_mode(); return status; } /* * Compile a MUTT file. */ static void compile_file() { static char filename[13] = { '\0' }; char fname[NFILEN]; if (!MUT_pathname[0]) { MUT_pathname[0] = Dgetdrv() + 'A'; MUT_pathname[1] = ':'; Dgetpath(&MUT_pathname[2],0); strcat(MUT_pathname,"\\*.MUT"); } if (!file_select(fname,"Compile a MUTT file",MUT_pathname,filename)) return; compile(fname); } /* * Compile the the current buffer. * * If the buffer is modified, save it first. */ static char *compile_buffer() { register char *fname; if (*(fname = get_dString(curbp->b_fname)) == '\0') { form_alert(1,"[3][This buffer is not|attached to a file!][Abort]"); return NULL; } if (strcmp(fname + strlen(fname) - 3, "mut")) { if (form_alert(2,"[2][This buffer does not seem|to contain a Mutt file.|Try to compile anyway?][Yes|No]") - 1) return NULL; } filesave(0,0); if (compile(fname)) return NULL; return fname; } /* * Compile the current buffer and load the compiled * MUTT file. */ static void run_buffer() { register char *p; char *mut_fname; char mco_fname[NFILEN]; if ((mut_fname = compile_buffer()) == NULL) return; Cursor_off(); strcpy(mco_fname,mut_fname); p = mco_fname + strlen(mco_fname) - 2; *p++ = 'c'; *p = 'o'; refresh(FALSE,1); redraw_text_window(); MMload(mco_fname,TRUE); Cursor_on(); } /* * Load an *.mut file. */ static void load_mut() { static char filename[13] = { '\0' }; char path[NFILEN]; if (!MUT_pathname[0]) { MUT_pathname[0] = Dgetdrv() + 'A'; MUT_pathname[1] = ':'; Dgetpath(&MUT_pathname[2],0); strcat(MUT_pathname,"\\*.MUT"); } if (!file_select(path,"Load a MUTT source file",MUT_pathname,filename)) return; filevisit_guts(path); } /* * Load an *.mco file. */ static void load_mco() { static char filename[13] = { '\0' }; char path[NFILEN]; if (!MCO_pathname[0]) { MCO_pathname[0] = Dgetdrv() + 'A'; MCO_pathname[1] = ':'; Dgetpath(&MCO_pathname[2],0); strcat(MCO_pathname,"\\*.MCO"); } if (!file_select(path,"Load a compiled MUTT file",MCO_pathname,filename)) return; top_text_window(); redraw_text_window(); Cursor_off(); MMload(path,TRUE); Cursor_on(); } /* * Locate the MUTT compiler. */ static void locate_mc2() { register char *p; char pathname[NFILEN]; char filename[13]; strcpy(pathname,MC2); if (!pathname[0]) { filename[0] = '\0'; pathname[0] = Dgetdrv() + 'A'; pathname[1] = ':'; Dgetpath(&pathname[2],0); } else { p = strrchr(pathname,'\\'); *p = '\0'; strcpy(filename, p + 1); } strcat(pathname,"\\*.TTP"); file_select(MC2,"Locate MC2",pathname,filename); } /* * Display the options dialog box. * * Return value: 0 - Ok * 1 - Cancel */ static int options_dialog(s) char *s; { OBJECT *box; TEDINFO *ted; int x,y,w,h; int obj; rsrc_gaddr(R_TREE,RSC_CMD_BOX,&box); ted = (TEDINFO *) box[RSC_OPTIONS].ob_spec; strcpy(ted->te_ptext,s); form_center(box,&x,&y,&w,&h); form_dial(FMD_START,0,0,0,0,x,y,w,h); objc_draw(box,ROOT,MAX_DEPTH,x,y,w,h); obj = form_do(box,RSC_OPTIONS) & 0x7fff; objc_change(box,obj,0,x,y,w,h,NORMAL,0); form_dial(FMD_FINISH,0,0,0,0,x,y,w,h); if (obj == RSC_OK3) { strcpy(s,ted->te_ptext); return 0; } else return 1; } /* * Execute a GEM program. */ static void exec_prg(mask,params) char *mask; int params; { static char pathname[NFILEN]; static char filename[13]; static char args[128]; char path[NFILEN]; char cmd[NFILEN+128]; char current_path[NFILEN]; char ch; char *pch; /* put a `volatile' before `char' when using a gcc < 2.4.2 */ int current_drive; if (params) { if (options_dialog(args)) return; } if (!pathname[0]) { pathname[0] = Dgetdrv() + 'A'; pathname[1] = ':'; Dgetpath(&pathname[2],0); strcat(pathname,"\\"); strcat(pathname,mask); } else strcpy(strrchr(pathname,'\\') + 1, mask); if (!file_select(path,"Execute a GEM application",pathname,filename)) return; ttclose(); graf_mouse(M_OFF,NULL); Dgetpath(current_path,0); current_drive = Dgetdrv(); Dsetdrv(toupper(path[0]) - 'A'); pch = strrchr(path,'\\'); ch = *++pch; *pch = '\0'; Dsetpath(path + 2); *pch = ch; if (params) { strcpy(cmd,path); strcat(cmd," "); strcat(cmd,args); system(cmd); } else system(path); Dsetdrv(current_drive); Dsetpath(current_path); redraw_screen(); graf_mouse(M_ON,NULL); ttopen(); } /* * Execute a TOS program. */ static void exec_tos(mask,params) char *mask; int params; { static char pathname[NFILEN]; static char filename[13]; static char args[128]; char path[NFILEN]; char cmd[NFILEN+128]; if (params) { if (options_dialog(args)) return; } if (!pathname[0]) { pathname[0] = Dgetdrv() + 'A'; pathname[1] = ':'; Dgetpath(&pathname[2],0); strcat(pathname,"\\"); strcat(pathname,mask); } else strcpy(strrchr(pathname,'\\') + 1, mask); if (!file_select(path,"Execute a TOS application",pathname,filename)) return; TOS_mode(); if (params) { strcpy(cmd,path); strcat(cmd," "); strcat(cmd,args); system(cmd); } else system(path); Cconws("\n[Hit Return to resume editing]"); Cconin(); GEM_mode(); } /* * The user selected a menu item, react to it. * * NOTE: Mouse pointer and cursor are ON upon entering this * function. On return they have to be ON, too. */ static void menu_item(title,entry) int title; int entry; { menu_tnormal(Menu,title,1); switch (entry) { case RSC_ABOUT : display_about_box(); break; case RSC_LOAD : top_text_window(); GEM_filevisit(0,0); break; case RSC_SAVE : filesave(0,0); redraw_text_window(); break; case RSC_SAVESET : save_setup(); break; case RSC_QUIT : terminate(); break; case RSC_FULLWIND : new_window_size(Fullh / Hchar, Fullw / Wchar); break; case RSC_STDWIND : new_window_size(Fullh / Hchar, (Fullw / Wchar > 80 ? 80 : Fullw / Wchar)); break; case RSC_NEWSIZE : new_size_dialog(); break; case RSC_BUFFWIND : if (Buffers_window > 0) close_buffers_window(); else open_buffers_window(); break; case RSC_GOBBLE : menu_icheck(Menu, RSC_GOBBLE, Gobble_arrow_events = !Gobble_arrow_events); break; case RSC_REDRAW : redraw_screen(); break; case RSC_8PT : new_font(8,RSC_8PT); break; case RSC_9PT : new_font(9,RSC_9PT); break; case RSC_10PT : new_font(10,RSC_10PT); break; case RSC_16PT : new_font(16,RSC_16PT); break; case RSC_18PT : new_font(18,RSC_18PT); break; case RSC_20PT : new_font(20,RSC_20PT); break; case RSC_COMPFILE : compile_file(); break; case RSC_COMPBUFF : compile_buffer(); break; case RSC_RUNBUFF : run_buffer(); break; case RSC_LOADMUT : load_mut(); break; case RSC_LOADMCO : load_mco(); break; case RSC_LOCMC2 : locate_mc2(); break; case RSC_MC2WAIT : menu_icheck(Menu, RSC_MC2WAIT, Wait_flag = !Wait_flag); break; case RSC_MC2OPT : options_dialog(MC2_options); break; case RSC_EXECPRG : exec_prg("*.PRG",0); break; case RSC_EXECGTP : exec_prg("*.GTP",1); break; case RSC_EXECAPP : exec_prg("*.APP",0); break; case RSC_EXECTTP : exec_tos("*.TTP",1); break; case RSC_EXECTOS : exec_tos("*.TOS",0); break; case RSC_SHELL : spawn_shell(0,0); } } /* * Process a redraw message from the window manager. */ static void redraw_window(window,x,y,w,h) int window; int x,y,w,h; { extern short Cursor_visible(); static short virgin = 1; GRECT redraw; GRECT part; int pxyarray[4]; int vw; if (window == Text_window) { if (virgin) { virgin = 0; return; } Cursor_off(); vw = Vw_print; } else { vw = Bw.vw_text; if (Cursor_visible) graf_mouse(M_OFF,NULL); } redraw.g_x = x; redraw.g_y = y; redraw.g_w = w; redraw.g_h = h; wind_update(BEG_UPDATE); Clip_sem = 1; if (wind_get(window,WF_FIRSTXYWH,&part.g_x,&part.g_y,&part.g_w,&part.g_h)) { while (part.g_w && part.g_h) { if (rc_intersect(&redraw,&part)) { pxyarray[0] = part.g_x; pxyarray[1] = part.g_y; pxyarray[2] = part.g_x + part.g_w - 1; pxyarray[3] = part.g_y + part.g_h - 1; vs_clip(vw,1,pxyarray); if (window == Text_window) { refresh(FALSE,1); update(); } else update_bw(); } wind_get(window,WF_NEXTXYWH,&part.g_x,&part.g_y,&part.g_w,&part.g_h); } } vs_clip(vw,0,pxyarray); Clip_sem = 0; wind_update(END_UPDATE); if (window == Text_window) Cursor_on(); else { if (Cursor_visible) graf_mouse(M_ON,NULL); } } /* * Redraw the buffers window. */ void redraw_buffers_window() { if (Buffers_window > 0) redraw_window(Bw.whandle,Bw.wx,Bw.wy,Bw.ww,Bw.wh); } /* * Redraw the text window. */ void redraw_text_window() { redraw_window(Text_window,Workx,Worky,Workw,Workh); } /* * Process a `window fulled' message for the text window. */ static void text_window_fulled(window) int window; { int x,y,w,h; GRECT prev; GRECT curr; GRECT full; wind_get(window,WF_CURRXYWH,&curr.g_x,&curr.g_y,&curr.g_w,&curr.g_h); wind_get(window,WF_PREVXYWH,&prev.g_x,&prev.g_y,&prev.g_w,&prev.g_h); wind_get(window,WF_FULLXYWH,&full.g_x,&full.g_y,&full.g_w,&full.g_h); wind_calc(WC_WORK,Wkind,curr.g_x,curr.g_y,curr.g_w,curr.g_h,&x,&y,&w,&h); if (w / Wchar == Fullw / Wchar && h / Hchar == Fullh / Hchar) { /* * The window is full, change to previous */ graf_shrinkbox(full.g_x,full.g_y,full.g_w,full.g_h, prev.g_x,prev.g_y,prev.g_w,prev.g_h); wind_calc(WC_WORK,Wkind,prev.g_x,prev.g_y,prev.g_w,prev.g_h, &x,&y,&w,&h); } else { /* * The window is not full, set it to full */ graf_growbox(curr.g_x,curr.g_y,curr.g_w,curr.g_h, full.g_x,full.g_y,full.g_w,full.g_h); wind_calc(WC_WORK,Wkind,full.g_x,full.g_y,full.g_w,full.g_h, &x,&y,&w,&h); } Cursor_x -= Workx - x; Cursor_y -= Worky - y; Workx = x; Worky = y; new_window_size(h / Hchar, w / Wchar); } /* * Process a `window fulled' message for the buffers window. */ static void buffers_window_fulled(wh) int wh; { GRECT prev; GRECT curr; GRECT full; wind_get(wh,WF_CURRXYWH,&curr.g_x,&curr.g_y,&curr.g_w,&curr.g_h); wind_get(wh,WF_PREVXYWH,&prev.g_x,&prev.g_y,&prev.g_w,&prev.g_h); wind_get(wh,WF_FULLXYWH,&full.g_x,&full.g_y,&full.g_w,&full.g_h); if (rc_equal(&curr,&full)) { graf_shrinkbox(prev.g_x,prev.g_y,prev.g_w,prev.g_h, full.g_x,full.g_y,full.g_w,full.g_h); wind_set(wh,WF_CURRXYWH,prev.g_x,prev.g_y,prev.g_w,prev.g_h); wind_calc(WC_WORK,Bw.wkind,prev.g_x,prev.g_y,prev.g_w,prev.g_h, &Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh); } else { graf_growbox(curr.g_x,curr.g_y,curr.g_w,curr.g_h, full.g_x,full.g_y,full.g_w,full.g_h); wind_set(wh,WF_CURRXYWH,full.g_x,full.g_y,full.g_w,full.g_h); wind_calc(WC_WORK,Bw.wkind,full.g_x,full.g_y,full.g_w,full.g_h, &Bw.wx,&Bw.wy,&Bw.ww,&Bw.wh); } } /* * Process a `window arrowed' message. */ static void window_arrowed(window,type) int window; int type; { static short gobble = 0; register int n; if (window != Bw.whandle) return; if (Gobble_arrow_events && gobble) { gobble = 0; return; } gobble = 1; switch (type) { case WA_UPLINE : if (Bw.y_offset > 0) { --Bw.y_offset; update_bw(); } break; case WA_DNLINE : if (Bw.nlines - Bw.y_offset > Bw.wh / Bw.hchar) { Bw.y_offset++; update_bw(); } break; case WA_UPPAGE : if (Bw.y_offset > 0) { n = Bw.wh / Bw.hchar; if (Bw.y_offset >= n) Bw.y_offset -= n; else Bw.y_offset = 0; update_bw(); } break; case WA_DNPAGE : n = Bw.wh / Bw.hchar; if (Bw.nlines - Bw.y_offset - n > Bw.wh / Bw.hchar) Bw.y_offset += n; else Bw.y_offset = Bw.nlines - n; update_bw(); } } /* * Process a `window topped' message for the buffers window. */ static void buffers_window_topped(mx,my) int mx,my; { register Buffer *b; register int n; n = (my - Bw.wy) / Bw.hchar + Bw.y_offset; b = first_buffer; while (n > 0 && b != NULL) { --n; b = b->nextb; } if (n < 0 || b == NULL || mx < Bw.wx || mx > Bw.wx + Bw.ww || my < Bw.wy || my > Bw.wy + Bw.wh) { wind_set(Bw.whandle,WF_TOP,0,0,0,0); redraw_buffers_window(); } else { use_buffer(b,TRUE); redraw_text_window(); } } /* * Move the modeline of an ME2 window up or down the GEM window. * Resize the corresponding ME2 window when the user releases * the mouse button. */ static void move_modeline(window,my) register Window *window; int my; { extern void grow_window(); register int n; /* # of lines to grow `window' */ register Window *other_window; /* window below `window' */ int x,y; if ((other_window = window->nextw) == NULL) return; graf_dragbox(Workw, Hchar, Workx, Worky + my * Hchar, Workx, Worky + (window->w_toprow + 1) * Hchar, Workw, (window->w_ntrows + other_window->w_ntrows - 1) * Hchar, &x, &y); n = (y - Worky) / Hchar - my; if (n > 0) { if (n >= other_window->w_ntrows) { t_beep(); return; } grow_window(window,other_window,n,TRUE); } else if (n < 0) { n = -n; if (n >= window->w_ntrows) { t_beep(); return; } grow_window(other_window,window,n,FALSE); } } /* * Process a button event. * * If the mouse pointer is on a mode line, resize the window. * If the mouse pointer is not in the current window, make that * window the current window. * Otherwise position the cursor at the location of the mouse * pointer. */ static void button_event(mx,my) int mx,my; { register Window *win; register Line *line; register Buffer *b; register int offset; if ((offset = wind_find(mx,my)) == Bw.whandle) { /* * The buffers window. */ offset = (my - Bw.wy) / Bw.hchar + Bw.y_offset; b = first_buffer; while (offset > 0 && b != NULL) { --offset; b = b->nextb; } if (offset >= 0 && b != NULL) { use_buffer(b,TRUE); redraw_text_window(); } } else if (offset == Text_window) { /* * The text window. */ mx = (mx - Workx) / Wchar; my = (my - Worky) / Hchar; if (my >= curwp->w_toprow && my < curwp->w_toprow + curwp->w_ntrows) { /* * The mouse pointer is in the current ME2 window. * Set the cursor to that point. */ for (line = curwp->top_line, offset = 0; line; line = line->l_next, offset++) { if (line == the_dot->line) break; } if (line == NULL) { t_beep(); return; } offset = (my - curwp->w_toprow) - offset; next_line(offset); the_dot->offset = getgoal(the_dot->line, mx + curwp->lmargin); display_buffer(curwp); } else { /* * Find the ME2 window under the mouse pointer position. */ for (win = first_window; win; win = win->nextw) { offset = win->w_toprow + win->w_ntrows; if (my >= win->w_toprow && my <= offset) break; } if (win == NULL) return; if (my == offset) move_modeline(win,my); else use_window(win); } Cursor_off(); update(); Cursor_on(); } } /* * The main GEM event loop. * * Returns when a keyboard event occured. */ KeyCode events() { int evnts; int i; int key,mx,my,mb,ks; int msg[8]; wind_update(END_UPDATE); wind_update(END_MCTRL); Cursor_on(); for (;;) { /* * Wait for the mouse button to be released. */ do vq_mouse(Phys_handle,&evnts,&i,&i); while (evnts); evnts = evnt_multi(EVENTS, /* Events to wait for */ 1, 1, 1, /* evnt_button */ 0, 0, 0, 0, 0, /* evnt_mouse (1) */ 0, 0, 0, 0, 0, /* evnt_mouse (2) */ msg, /* evnt_mesag */ 1000L, /* evnt_timer (1 sec) */ &mx, &my, &mb, /* Return values */ &ks, &key, &i /* Return values */ ); if (evnts & MU_MESAG) { switch (msg[0]) { case MN_SELECTED : menu_item(msg[3],msg[4]); break; case WM_REDRAW : redraw_window(msg[3],msg[4],msg[5],msg[6],msg[7]); break; case WM_TOPPED : if (msg[3] == Text_window) top_text_window(); else if (msg[3] == Bw.whandle) buffers_window_topped(mx,my); break; case WM_MOVED : window_moved(msg[3],msg[4],msg[5],msg[6],msg[7]); break; case WM_SIZED : window_sized(msg[3],msg[4],msg[5],msg[6],msg[7]); break; case WM_FULLED : if (msg[3] == Text_window) text_window_fulled(msg[3]); else if (msg[3] == Bw.whandle) buffers_window_fulled(msg[3]); break; case WM_CLOSED : close_buffers_window(); break; case WM_ARROWED : window_arrowed(msg[3],msg[4]); break; case WM_VSLID : i = Bw.nlines - Bw.wh / Bw.hchar; if (i < 0) Bw.y_offset = 0; else Bw.y_offset = (msg[4] * i) / 1000; update_bw(); } } if (evnts & MU_BUTTON) button_event(mx,my); if (evnts & MU_KEYBD) { Cursor_off(); wind_update(BEG_UPDATE); wind_update(BEG_MCTRL); if (Buffers_window > 0) top_text_window(); return getkeyX(key); } } } /* * The following two functions, `presub' and `pathfind' * are stolen from Tim Gallivan's `gemgs' program and * sligthly modified. */ #define MAXLEN 255 /* Presub(s, subs) searches the string s for the substring subs. Presub * returns a pointer to the NULL terminated substring which immediately * preceeds subs. If presub is called again with a NULL pointer for s, * it returns a pointer to the substring between the previous subs and * the current subs. If subs is a null character, presub returns a pointer * to the portion of s between the previous subs and the end of s. */ static char *presub(s, subs) char *s, *subs; { int sublen; char *mptr; static int count; static char match[MAXLEN], *ptr; if (s != NULL) { ptr = s; count = 0; } mptr = match + count; if ((sublen = strlen(subs)) == 0) { strcpy(mptr, ptr); return (mptr); } while (*ptr != '\0') { if (strncmp(ptr, subs, sublen) == 0) { match[count] = '\0'; ptr += sublen; ++count; return (mptr); } match[count] = *ptr; ++ptr; ++count; } if ((match + count) > mptr) { match[count] = *ptr; ++count; return (mptr); } return (NULL); } /* Pathfind(path, file, sep) searches for 'file' in the path given * by the envionment variable named in 'env'. Sep specifies the * path separator. It returns a pointer to the filename if it is * found, and a NULL if not. */ char *pathfind(char *env, char *file, char *sep) { FILE *fp; extern char *getenv(); char path[2*MAXLEN]; static char name[MAXLEN]; char *ptr; if ((fp = fopen(file, "r")) == NULL) { if ((ptr = getenv(env)) != NULL) { strcpy(path, ptr); } else { return NULL; } if ((ptr = presub(path, sep)) == NULL) { return NULL; } do { strcpy(name, ptr); if (name[strlen(name)-1] != '\\' || name[strlen(name)-1] != '/') strcat(name, "\\"); strcat(name, file); if ((fp = fopen(name, "r")) != NULL) { fclose(fp); strcpy(path,name); _lib_unx2dos(path,name); return name; } } while ((ptr = presub(NULL, sep)) != NULL); } else { fclose(fp); return file; } } #undef MAXLEN