/* This function converts key labels to raw codes */ static int keylabel (ELVCHAR *given, /* what the user typed in as the key name */ int givenlen, /* length of the "given" string */ ELVCHAR **label, /* standard name for that key */ ELVCHAR **rawptr) /* control code sent by that key */ { int i; /* compare the given text to each key's strings */ for (i = 0; i < QTY(keys); i++) { /* ignore unsupported keys */ if (!keys[i].rawin) continue; /* does given string match key label or raw characters? */ if ((!strncmp(keys[i].label, tochar8(given), (size_t)givenlen) && !keys[i].label[givenlen]) || (!strncmp(keys[i].rawin, tochar8(given), (size_t)givenlen) && !keys[i].rawin[givenlen])) { /* Set the label and rawptr pointers, return rawlen */ *label = toCHAR(keys[i].label); *rawptr = toCHAR(keys[i].rawin); return CHARlen(*rawptr); } } /* We reached the end of the keys[] array without finding a match, * so this given string is not a key. */ return 0; }
static int swapsystem(char *cmd) { char *prog, *args; int retcode; for (; elvspace(*cmd); cmd++) { } prog = safedup(cmd); for (args = prog; *args && !elvspace(*args); args++) { } if (*args) *args++ = '\0'; retcode = do_exec(prog, args, USE_ALL|HIDE_FILE, 0xFFFF, NULL); if (retcode == RC_NOFILE) { safefree(prog); prog = safealloc(strlen(cmd) + 4, sizeof(char)); strcpy(prog, "/c "); strcat(prog, cmd); retcode = do_exec(tochar8(o_shell), prog, USE_ALL|HIDE_FILE, 0xFFFF, NULL); } safefree(prog); return retcode; }
static void gwretitle (GUIWIN *gw, char *name) { GUI_WINDOW *gwp = (GUI_WINDOW *)gw; #if 0 char title[_MAX_PATH + 20]; BUFFER buf; buf = buffind(toCHAR(name)); if (buf && o_filename(buf)) name = tochar8(o_filename(buf)); sprintf (title, "WinElvis - [%s]", name); SetWindowText (gwp->frameHWnd, title); #else Char *argv[2]; Char *title; ELVBOOL wasmsg; /* evaluate the titleformat string */ argv[0] = (Char *)name; argv[1] = NULL; title = o_titleformat(gwp); if (!title) title = (Char *)"$1"; wasmsg = msghide(ElvTrue); title = calculate(title, argv, CALC_MSG); msghide(wasmsg); if (title && *title) name = (char *)title; /* change the window's title */ SetWindowText (gwp->frameHWnd, name); #endif }
/* Declares which program we'll run, and what we'll be doing with it. * This function should return ElvTrue if successful. If there is an error, * it should issue an error message via msg(), and return ElvFalse. */ ELVBOOL prgopen(char *command, ELVBOOL willwrite, ELVBOOL willread) { /* remember the command we're supposed to run */ cmd = command; /* if we're going to be reading, then choose a tempread name now */ if (willread) { strcpy(tempread, o_directory ? dirpath(tochar8(o_directory), "rdXXXXXX") : "rdXXXXXX"); mktemp(tempread); /* open it and close it, just to make sure it exists */ fd = open(tempread, O_WRONLY|O_CREAT|O_EXCL, 0600); if (fd < 0) { msg(MSG_ERROR, "[s]can't create temp file $1", tempread); return ElvFalse; } close(fd); } else tempread[0] = '\0'; /* if we'll be writing, then choose a tempwrite name and open it */ if (willwrite) { strcpy(tempwrite, o_directory ? dirpath(tochar8(o_directory), "wrXXXXXX") : "wrXXXXXX"); mktemp(tempwrite); fd = open(tempwrite, O_WRONLY|O_CREAT|O_EXCL, 0600); if (fd < 0) { msg(MSG_ERROR, "[s]can't create temp file $1", tempwrite); if (tempread[0]) remove(tempread); return ElvFalse; } } else tempwrite[0] = '\0'; return ElvTrue; }
/* This function closes the session file, given its handle */ void blkclose (BLK *buf) /* buffer, holds superblock */ { blkread (buf, 0); buf->super.inuse = 0L; blkwrite (buf, 0); (void)DosClose (fd); fd = NULLHANDLE; if (o_tempsession) { (void)DosDelete (tochar8(o_session)); } /* if */ }
static int gwkeylabel (Char *given, int givenlen, Char **label, Char **rawptr) { register int i; /* compare the given text to each key's strings */ for (i = 0; gwkeys[i].label != 0; i++) { /* does given string match key label or raw characters? */ if ((!strncmp (gwkeys[i].label, tochar8 (given), (size_t)givenlen) && !gwkeys[i].label[givenlen]) || (!strncmp (gwkeys[i].rawin, tochar8 (given), (size_t)givenlen) && !gwkeys[i].rawin[givenlen])) { /* Set the label and rawptr pointers, return rawlen */ *label = (unsigned char *)gwkeys[i].label; *rawptr = (unsigned char *)gwkeys[i].rawin; return strlen ((char *)*rawptr); } } return 0; }
static int RunCommand (char *command) { char *buffer; char *shell; int pid; /* Locate the command shell. */ shell = o_shell ? tochar8 (o_shell) : getenv ("COMSPEC"); if (shell == NULL) { shell = "cmd.exe"; } if ((buffer = malloc (strlen (command) + 5)) != NULL) { /* * Herbert: * Find the name of the shell. I assume cmd.exe and 4os2.exe to * understand the "/c" switch and use "-c" for all the others. * The quotes around the command *seem* to work for Unix-like * shells, they are meant to pass the command to the shell as * one string. */ char *org_sep = strrchr (shell, OSPATHSEP); char *alt_sep = strrchr (shell, OSALTPSEP); char *base = org_sep < alt_sep ? alt_sep : org_sep; base = base == NULL? shell: base+1; if ( stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0) { sprintf (buffer, "/c %s", command); } else { sprintf (buffer, "-c \"%s\"", command); } pid = spawnlp (P_NOWAIT, shell, shell, buffer, NULL); free (buffer); return pid; } else { return -1; } }
static RESULT gwstop (ELVBOOL alwaysform) { PROCESS_INFORMATION proc; STARTUPINFO start; /* save the buffers, if we're supposed to */ eventsuspend (); /* start the process */ memset (&start, 0, sizeof (start)); start.cb = sizeof (start); if (CreateProcess (NULL, o_shell ? o_shell : tochar8 (o_shell), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | NORMAL_PRIORITY_CLASS, NULL, NULL, &start, &proc)) return RESULT_COMPLETE; /* dang! */ return RESULT_ERROR; }
/* Marks the end of writing. Returns ElvTrue if all is okay, or ElvFalse if * error. */ ELVBOOL prggo(void) { int old0; /* elvis' stdin */ int old1; /* elvis' stdout */ int old2; /* elvis' stderr */ CHAR *arg[3];/* arguments when evaluating command string */ /* are we supposed to redirect stdin? */ if (tempwrite[0]) { /* close the file we've been writing to */ close(fd); /* save the old stdin as another fd so we can switch back later */ old0 = dup(0); assert(old0 > 2); /* open the temp file as stdin */ close(0); #ifdef NDEBUG (void)open(tempwrite, O_RDONLY); #else assert(open(tempwrite, O_RDONLY) == 0); #endif } /* are we supposed to redirect stdout/stderr ? */ if (tempread[0]) { /* save the old stdout and stderr as other fds */ old1 = dup(1); old2 = dup(2); assert(old1 > 2 && old2 > 2); /* open the temp file as stdout/stderr */ close(1); close(2); #ifdef NDEBUG (void)open(tempread, O_WRONLY); dup(1); #else assert(open(tempread, O_WRONLY) == 1); assert(dup(1) == 2); #endif } #if 0 /* if redirecting anything, then evaluate the command string like a * message, substituting the input and/or output files for $1 and $2 */ if ((tempwrite[0] || tempread[0]) && CHARchr(cmd, '$')) { arg[0] = toCHAR(tempwrite); arg[1] = toCHAR(tempread); arg[2] = NULL; cmd = tochar8(calculate(toCHAR(cmd), arg, CALC_MSG)); if (!cmd) { if (tempwrite[0]) remove(tempwrite); if (tempread[0]) remove(tempread); return ElvFalse; } } #endif /* run the program */ status = swapsystem(cmd); /* if we redirected stdin, undo it now */ if (tempwrite[0]) { /* undo the redirection */ close(0); #ifdef NDEBUG (void)dup(old0); #else assert(dup(old0) == 0); #endif close(old0); /* delete the temp file */ remove(tempwrite); } /* if we redirected stdout/stderr, undo it now and open the temp file */ if (tempread[0]) { /* undo the redirection */ close(1); close(2); #ifdef NDEBUG (void)dup(old1); (void)dup(old2); #else assert(dup(old1) == 1); assert(dup(old2) == 2); #endif close(old1); close(old2); /* open the temp file */ fd = open(tempread, O_RDONLY); assert(fd > 0); } return ElvTrue; }
/* put characters: first move, then set attribute, then execute char. */ static void vio_draw (GUIWIN *gw, /* window where text should be drawn */ long fg, /* foreground color */ long bg, /* background color */ int bits, /* other attributes */ ELVCHAR *text, /* text to draw */ int len) /* length of text */ { VWIN *vw = (GUIWIN *)gw; int i; #ifndef NDEBUG VWIN *scan; for (scan = vwins; scan != vw && scan; scan = scan->next) { } assert (scan); #endif /* if COLOR_LEFTBOX is set, but not COLOR_BOXED, then draw in two * phases: First draw a single character with COLOR_LEFTBOX, and then * draw the remainder without COLOR_LEFTBOX. */ if ((bits & (COLOR_LEFTBOX|COLOR_BOXED)) == COLOR_LEFTBOX && len > 1) { vio_draw(gw, fg, bg, bits, text, 1); bits &= ~COLOR_LEFTBOX; text++; len--; } /* After a program, don't output any text except messages for a while. * This is mostly an optimization; the window is about to be redrawn * from scratch anyway. But it also prevents the screen from doing * strange, unexpected things. */ if (afterprg > 0) { #if 0 fprintf (stderr, "draw(\"%.*s\"), vw->cursy=%d, vw->height=%d, physy=%d, afterscrl=%d\n", len, tochar8 (text), vw->cursy, vw->height, physy, afterscrl); #endif if (vw->cursy < vw->height - afterscrl - 1) return; /* * movecurs() could put us on the wrong row if the current * window isn't the one on the bottom; however, we still * need to be able to adjust the column in order to be * correct for all values of (guivio.movecost). */ c_col = vw->cursx; } else { /* move the cursor to where this window thinks it is */ movecurs (vw); } /* if graphic characters, then handle specially */ if (bits & COLOR_GRAPHIC) { drawgraphic (gw, fg, bg, bits, text, len); return; } /* If we're on the bottom row of a window (except the last window) * then any normal characters should be underlined. This will give * us the effect of a window border. */ if (vw->cursy == vw->height - 1 && physy < o_ttyrows - 1) { bits |= COLOR_UNDERLINED; } change (fg, bg, bits); /* draw each character. If this is the bottom row of any window except * the bottom window, then also replace any blanks with '_' characters. * This will provide a window border in case the terminal can't do * real underlining. */ if (vw->cursy == vw->height - 1 && physy < o_ttyrows - 1) { for (i = 0; i < len; i++) { ttych (text[i] == ' ' ? '_' : text[i]); } } else /* normal row */ { for (i = 0; i < len; i++) { ttych (text[i]); } } /* drawing the characters has the side-effect of moving the cursor */ vw->cursx += len; physx += len; }
static ELVBOOL gwcolor (int fontcode, Char *colornam, ELVBOOL isfg, long *colorptr, unsigned char rgb[3]) { register int i, j; int r, g, b; char *rgbfile; char rgbname[100]; FILE *fp; #ifdef FEATURE_IMAGE HBITMAP newimg; long average; char *imagefile; /* split the name into a "colornam" part and an "imagefile" part */ imagefile = colornam; if (*imagefile == '#') imagefile++; while (*imagefile && !elvpunct(*imagefile)) imagefile++; while (*imagefile && imagefile > colornam && !elvspace(*imagefile)) imagefile--; if (!*imagefile) imagefile = NULL; else if (imagefile > colornam) *imagefile++ = '\0'; else colornam = ""; #endif /* parse the color name */ if (*colornam == '#') { /* Accept X11's "#rrggbb" or "#rgb" notations */ if (sscanf(tochar8(colornam), "#%2x%*2x%2x%*2x%2x", &r, &g, &b) == 3) /* do nothing */; else if (sscanf(tochar8(colornam), "#%2x%2x%2x", &r, &g, &b) == 3) /* do nothing */; else if (sscanf(tochar8(colornam), "#%1x%1x%1x", &r, &g, &b) == 3) { r *= 17; g *= 17; b *= 17; } else { msg(MSG_ERROR, "[S]bad color notation $1", colornam); return ElvFalse; } } else if (!*colornam) { r = g = b = -1; } else { /* Normalize the color name by converting to lowercase and removing * whitespace. We can safely modify the colornam[] buffer in-place. */ for (i = j = 0; colornam[i]; i++) if (!elvspace(colornam[i])) colornam[j++] = elvtolower(colornam[i]); colornam[j] = '\0'; /* look up the color */ for (i = 0; colortbl[i].name && CHARcmp(toCHAR(colortbl[i].name), colornam); i++) { } if (colortbl[i].name) { /* Use the found color */ r = colortbl[i].rgb[0]; g = colortbl[i].rgb[1]; b = colortbl[i].rgb[2]; } else /* not found -- try "rgb.txt" */ { /* search for the color in the "rgb.txt" file */ *rgbname = '\0'; rgbfile = iopath(o_elvispath, "rgb.txt", ElvFalse); if (rgbfile) { fp = fopen(rgbfile, "r"); if (fp) { while (fscanf(fp, "%d %d %d %s", &r, &g, &b, &rgbname) == 4 && CHARcmp(tochar8(rgbname), colornam)) { } fclose(fp); } } /* if we didn't find it there, then fail */ if (CHARcmp(tochar8(rgbname), colornam)) { if (isfg) { memcpy(rgb, colorinfo[COLOR_FONT_NORMAL].da.fg_rgb, 3); *colorptr = colorinfo[COLOR_FONT_NORMAL].fg; } else { memcpy(rgb, colorinfo[COLOR_FONT_NORMAL].da.bg_rgb, 3); *colorptr = colorinfo[COLOR_FONT_NORMAL].bg; } msg(MSG_ERROR, "[S]unknown color $1", colornam); return ElvFalse; } } } #ifdef FEATURE_IMAGE if (imagefile && isfg) { msg(MSG_ERROR, "Can't use images for foreground"); return ElvFalse; } #endif /* if no image or color, then fail */ if ( #ifdef FEATURE_IMAGE !imagefile && #endif r < 0) { msg(MSG_ERROR, "missing color name"); return ElvFalse; } #ifdef FEATURE_IMAGE /* if image name was given for "normal" or "idle" font, then load image */ if (imagefile && (fontcode==COLOR_FONT_NORMAL || fontcode==COLOR_FONT_IDLE)) { /* decide whether to use a tint */ if (r >= 0) average = RGB(r, g, b); else average = -1; /* load the image */ newimg = gw_load_xpm(imagefile, average, &average, NULL); if (newimg) { /* use the average colors */ r = GetRValue(average); g = GetGValue(average); b = GetBValue(average); /* if there was an old image, discard it now */ if (fontcode == COLOR_FONT_NORMAL && normalimage) gw_unload_xpm(normalimage); if (fontcode == COLOR_FONT_IDLE && idleimage) gw_unload_xpm(idleimage); /* store the new image */ if (fontcode == COLOR_FONT_NORMAL) normalimage = newimg; else idleimage = newimg; } else { return ElvFalse; } } if (!imagefile && fontcode==COLOR_FONT_NORMAL && normalimage && !isfg) { gw_unload_xpm(normalimage); normalimage = NULL; } if (!imagefile && fontcode==COLOR_FONT_IDLE && idleimage && !isfg) { gw_unload_xpm(idleimage); idleimage = NULL; } #endif /* Success! Store the color and return ElvTrue */ *colorptr = RGB(r, g, b); rgb[0] = r; rgb[1] = g; rgb[2] = b; return ElvTrue; }
/* This function creates a new block file, and returns ElvTrue if successful, * or ElvFalse if failed because the file was already busy. */ ELVBOOL blkopen (ELVBOOL force, /* if ElvTrue, open even if "in use" flag set */ BLK *buf) /* buffer, holds SUPER block */ { static char dfltname[256]; int i; APIRET rc; ULONG open_flags; ULONG open_mode; ULONG action; ULONG actual; #ifdef FEATURE_RAM if (o_session && !CHARcmp(o_session, toCHAR("ram"))) { nblks = 1024; blklist = (BLK **)calloc(nblks, sizeof(BLK *)); blklist[0] = (BLK *)malloc(o_blksize); memcpy(blklist[0], buf, o_blksize); return ElvTrue; } #endif /* This is a little bit dirty :-) We try to find a directory for * our session files from the list o_sessionpath. It will be the * first writable directory from the list we can find. The dirty * part is we don't want to do this more than once. */ if (sessionDirPtr == NULL) { char pathlist[128]; char *ptr = pathlist; unsigned last; FILESTATUS fileInfo = {{0}}; sprintf (sessionDir, "%c", OSPATHDELIM); /* search through sessionpath for a writable directory */ if (!o_sessionpath) o_sessionpath = toCHAR("."); /* endif */ /* Go through the directory list in o_sessionpath and use * the first writable one for the session file. */ pathlist[sizeof pathlist - 1u] = '\0'; strncpy (pathlist, o_sessionpath, sizeof pathlist - 1u); if ((ptr = strtok (pathlist, sessionDir)) != NULL) { do { last = strlen (ptr); if (ptr[last-1] == OSPATHSEP) ptr[last-1] = '\0'; /* endif */ if (DosQueryPathInfo ((PSZ)ptr, FIL_STANDARD, &fileInfo, (ULONG)sizeof fileInfo) == NO_ERROR && (fileInfo.attrFile & 0x01) == 0 && (fileInfo.attrFile & 0x10) != 0) break; /* endif */ } while ((ptr = strtok (NULL, sessionDir)) != NULL); }/* if */ /* Found a directory for the session file? If not, just use * the current one else use the one found. */ if (ptr == NULL) sprintf (sessionDir, "%c", '.'); else { strncpy (sessionDir, ptr, sizeof sessionDir - 1u); sessionDir[sizeof sessionDir - 1u] = '\0'; } /* if */ /* Append a path delimiter and terminate string. Be sure * not to write outside the buffer boundaries... */ if ((last = strlen (sessionDir)) < sizeof sessionDir - 1u){ sessionDir[last] = OSPATHSEP; sessionDir[last+1] = '\0'; }/* if */ } /* if */ /* If elvis runs other programs, prevent them from inheriting * the session file's descriptor. Also prevent write access * to the session file by other processes while this process * is using it. */ open_mode = OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READWRITE; /* If no session file was explicitly requested, try successive * defaults until we find an existing file (if we're trying to * recover) or a non-existent file (if we're not trying to recover). */ if (!o_session) { i = 1; o_session = toCHAR (dfltname); o_tempsession = ElvTrue; do { /* protect against trying a ridiculous number of files */ if (i >= 1000) { msg(MSG_FATAL, o_recovering ? "[s]no session file found in $1" : "[s]too many session files in $1", sessionDir); } sprintf (dfltname, DEFAULT_SESSION, sessionDir, i++); open_flags = o_recovering ? OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS : OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS; rc = DosOpen (tochar8 (o_session), &fd, &action, 0L, FILE_NORMAL, open_flags, open_mode, NULL); } while (rc == ERROR_OPEN_FAILED); } else { /* Try to open the session file */ open_flags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; rc = DosOpen (tochar8(o_session), &fd, &action, 0L, FILE_NORMAL, open_flags, open_mode, NULL); } /* if */ /* Error checking. */ switch (rc) { case NO_ERROR: break; case ERROR_SHARING_VIOLATION: msg(MSG_FATAL, "session file busy"); default: msg(MSG_FATAL, "no such session"); } /* if */ if (action == FILE_EXISTED) { /* we're opening an existing session -- definitely not temporary */ o_tempsession = ElvFalse; } else { o_newsession = ElvTrue; rc = DosWrite (fd, buf, BLKSIZE, &actual); if (rc != NO_ERROR || actual < BLKSIZE) { DosClose (fd); DosDelete (tochar8(o_session)); fd = NULLHANDLE; msg (MSG_FATAL, "no such session"); } else { (void)DosSetFilePtr (fd, 0L, FILE_BEGIN, &actual); } /* if */ } /* if */ /* Read the first block & mark the session file as being "in use". * If already marked as "in use" and !force, then fail. */ rc = DosRead (fd, buf, sizeof buf->super, &actual); if (rc != NO_ERROR || actual != sizeof buf->super) { msg (MSG_FATAL, "blkopen's read failed"); } /* if */ if (buf->super.inuse && !force) { return ElvFalse; } /* if */ buf->super.inuse = getpid(); (void)DosSetFilePtr (fd, 0L, FILE_BEGIN, &actual); (void)DosWrite (fd, buf, sizeof buf->super, &actual); /* done! */ return ElvTrue; }