home *** CD-ROM | disk | FTP | other *** search
- #line 2 "os_win.c" /* So compiler knows original name of this file.*/
- /*
- * $Id: os_win.c,v 4.32 1996/03/15 07:41:11 hubert Exp $
- *
- * Program: Operating system dependent routines - MS Windows 3.1
- *
- *
- * Tom Unger
- * Networks and Distributed Computing
- * Computing and Communications
- * University of Washington
- * Administration Builiding, AG-44
- * Seattle, Washington, 98195, USA
- * Internet: mikes@cac.washington.edu
- *
- * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
- *
- *
- * Pine and Pico are registered trademarks of the University of Washington.
- * No commercial use of these trademarks may be made without prior written
- * permission of the University of Washington.
- *
- * Pine, Pico, and Pilot software and its included text are Copyright
- * 1989-1996 by the University of Washington.
- *
- * The full text of our legal notices is contained in the file called
- * CPYRIGHT, included with this distribution.
- *
- *
- * Notes:
- * - mouse support added (mss, 921215)
- *
- * Portions of this code derived from MicroEMACS 3.10:
- *
- * MSDOS.C: Operating specific I/O and Spawning functions
- * under the MS/PCDOS operating system
- * for MicroEMACS 3.10
- * (C)opyright 1988 by Daniel M. Lawrence
- *
- */
-
- /*#include <windows.h>*/
-
- #include <stdio.h>
- #include <errno.h>
- #include <setjmp.h>
- #include <time.h>
- #include <fcntl.h>
- /*#include <io.h>*/
- /*#include <bios.h>*/
-
- #include "osdep.h"
- #include "pico.h"
- #include "estruct.h"
- #include "efunc.h"
- #include "edef.h"
- #include "pico.h"
- #include "dos_gen.h"
-
- #ifdef MOUSE
-
- #define MOUSE_BUTTONS 3
-
- #endif /* MOUSE */
-
- /*
- * Internal functions...
- */
- int timeout = 0;
- static int MapMSKEYtoPK (int c);
- static int ProcessMouse(MEvent *, unsigned int *);
- int ttopen ();
- int ttclose ();
-
-
- /*
- * Include generic DOS/Windows routines
- */
- #include "dos_gen.c"
-
-
- #define MARGIN 8 /* size of minimim margin and */
- #define SCRSIZ 64 /* scroll size for extended lines */
- #define MROW 2 /* rows in menu */
-
-
-
- /*
- * Standard terminal interface dispatch table. Fields point to functions
- * that operate the terminal. All these functions live in mswin.c, but
- * this structure is defined here because it is specific to pico.
- */
- TERM term = {
- 0,
- 0,
- MARGIN,
- SCRSIZ,
- MROW,
- ttopen,
- ttclose,
- mswin_getc,
- mswin_putc,
- mswin_flush,
- mswin_move,
- mswin_eeol,
- mswin_eeop,
- mswin_beep,
- mswin_rev
- };
-
-
- /*
- * mswin_resize - windows specific callback to set pico's internal tables
- * to new screen dimensions.
- */
- int
- mswin_resize (row, col)
- int row, col;
- {
- resize_pico (row-1, col);
- return (0);
- }
-
-
- /*
- * ttresize - recompute the screen dimensions if necessary, and then
- * adjust pico's internal buffers accordingly.
- */
- int ttresize ()
- {
- int row, col;
-
- mswin_getscreensize(&row, &col);
- resize_pico (row-1, col);
- }
-
-
- /*
- * This function is called once to set up the terminal device streams.
- */
- int
- ttopen()
- {
- int rows, columns;
-
-
- mswin_getscreensize (&rows, &columns);
- term.t_nrow = rows - 1;
- term.t_ncol = columns;
- term.t_scrsiz = (columns * 2) / 3;
-
- /*
- * Do we implement optimized character insertion and deletion?
- * o_insert() and o_delete()
- */
- inschar = delchar = FALSE;
- revexist = TRUE;
-
- mswin_setresizecallback (mswin_resize);
-
-
-
- #if MOUSE
- init_mouse();
- #else /* !MOUSE */
- mexist = 0;
- #endif /* MOUSE */
- return(1);
- }
-
-
- #ifdef MOUSE
- /*
- * init_mouse - check for and initialize mouse driver...
- */
- int
- init_mouse()
- {
- nbuttons = MOUSE_BUTTONS;
- return (mexist = TRUE); /* Mouse always exists under windows */
- }
-
-
- /*
- * mouseon - call made available for programs calling pico to turn ON the
- * mouse cursor.
- */
- void
- mouseon()
- {
- }
-
-
- /*
- * mouseoff - call made available for programs calling pico to turn OFF the
- * mouse cursor.
- */
- void
- mouseoff()
- {
- }
- #endif
-
-
-
- /*
- * This function gets called just before we go back home to the command
- * interpreter.
- */
- int
- ttclose()
- {
- mswin_clearresizecallback (mswin_resize);
- return(1);
- }
-
-
-
- /*
- * Flush terminal buffer. Does real work where the terminal output is buffered
- * up. A no-operation on systems where byte at a time terminal I/O is done.
- */
- int
- ttflush()
- {
- return(1);
- }
-
-
-
- /*
- * Read in a key.
- * Do the standard keyboard preprocessing. Convert the keys to the internal
- * character set. Resolves escape sequences and returns no-op if global
- * timeout value exceeded.
- */
- int
- GetKey ()
- {
- int ch = 0;
- unsigned int lch;
- long timein;
- MEvent mouse;
-
-
- ch = NODATA;
- timein = time(0L);
-
-
- /*
- * Main character processing loop.
- */
- while((ch = mswin_getc ()) == MSWIN_KEY_NODATA) {
-
- #if MOUSE
- /* Check Mouse. If we get a mouse event, convert to char
- * event and return that. */
- if (checkmouse (&ch,0,0,0)) {
- curwp->w_flag |= WFHARD;
- return (ch);
- }
- #endif /* MOUSE */
-
-
- /* Check Timeout. */
- if(time(0L) >= timein+timeout)
- return(NODATA);
- }
-
-
- return (MapMSKEYtoPK (ch));
- }
-
-
-
- static int
- MapMSKEYtoPK (int c)
- {
- switch (c) {
- case MSWIN_KEY_UP: return (K_PAD_UP);
- case MSWIN_KEY_DOWN: return (K_PAD_DOWN);
- case MSWIN_KEY_RIGHT: return (K_PAD_RIGHT);
- case MSWIN_KEY_LEFT: return (K_PAD_LEFT);
- case MSWIN_KEY_SCROLLUPPAGE:
- case MSWIN_KEY_PREVPAGE: return (K_PAD_PREVPAGE);
- case MSWIN_KEY_SCROLLDOWNPAGE:
- case MSWIN_KEY_NEXTPAGE: return (K_PAD_NEXTPAGE);
- case MSWIN_KEY_HOME: return (K_PAD_HOME);
- case MSWIN_KEY_END: return (K_PAD_END);
- case MSWIN_KEY_DELETE: return (K_PAD_DELETE);
- case MSWIN_KEY_F1: return (F1);
- case MSWIN_KEY_F2: return (F2);
- case MSWIN_KEY_F3: return (F3);
- case MSWIN_KEY_F4: return (F4);
- case MSWIN_KEY_F5: return (F5);
- case MSWIN_KEY_F6: return (F6);
- case MSWIN_KEY_F7: return (F7);
- case MSWIN_KEY_F8: return (F8);
- case MSWIN_KEY_F9: return (F9);
- case MSWIN_KEY_F10: return (F10);
- case MSWIN_KEY_F11: return (F11);
- case MSWIN_KEY_F12: return (F12);
- case MSWIN_KEY_SCROLLUPLINE: return (K_SCROLLUPLINE);
- case MSWIN_KEY_SCROLLDOWNLINE: return (K_SCROLLDOWNLINE);
- case MSWIN_KEY_SCROLLTO: return (K_SCROLLTO);
- case MSWIN_KEY_NODATA: return (NODATA);
- }
-
- /* Control keys. */
- if (c < ' ')
- return (CTRL | (c + '@'));
-
- /* Normal keys. */
- return (c);
- }
-
-
-
-
-
- #if MOUSE
- /*
- * checkmouse - Check mouse and return maped command.
- *
- * EXPORTED to pico.
- * NOTE: "down", "xxx", and "yyy" aren't used under windows.
- */
- int
- checkmouse (unsigned int *ch, int ddd, int xxx, int yyy)
- {
- static int oindex; /* Index of previous mouse down. */
- int k; /* current bit/button of mouse */
- int mcol; /* current mouse column */
- int mrow; /* current mouse row */
- int down; /* TRUE when mouse down event. */
- unsigned long r;
- int rv = 0; /* TRUE when we have something to return. */
- MEvent mouse;
- int i = 0;
- MENUITEM *mp;
-
-
- *ch = 0;
-
- /* Mouse installed? */
- if (!mexist)
- return (FALSE);
-
- if (!mswin_getmouseevent (&mouse))
- return (FALSE);
-
-
- /* Location of mouse event. */
- mcol = mouse.nColumn;
- mrow = mouse.nRow;
-
-
-
- /*
- * If there is a tracking function it gets all the mouse events
- * reguardless of where they occur.
- */
- if (mtrack != NULL) {
- r = mtrack (mouse.event, mrow, mcol, mouse.button, mouse.keys);
- if (r & 0xffff){
- *ch = (unsigned) ((r>>16) & 0xffff);
- rv = TRUE;
- }
- return (rv);
- }
-
-
-
-
- /* Mouse down or up? */
- if (mouse.event == M_EVENT_DOWN) { /* button down */
- oindex = -1; /* No Previous mouse down. */
- }
-
-
- /* In special screen region? */
- for(mp = mfunc; mp; mp = mp->next)
- if(mp->action && M_ACTIVE(mrow, mcol, mp))
- break;
-
- if(mp){
-
- r = (*mp->action)(mouse.event, mrow, mcol, mouse.button, mouse.keys);
- if (r & 0xffff){
- *ch = (unsigned) ((r>>16) & 0xffff);
- rv = TRUE;
- }
- }
- else{
-
- /* In any of the menuitems? */
- while(1){ /* see if we understand event */
- if(i >= 12){
- i = -1; /* Not Found. */
- break;
- }
-
- if(M_ACTIVE(mrow, mcol, &menuitems[i]))
- break; /* Found. */
-
- i++; /* Next. */
- }
-
- /* Now, was that a mouse down or mouse up? */
- if (mouse.event == M_EVENT_DOWN) { /* button down */
- oindex = i; /* remember where */
- if(i != -1) /* invert label */
- invert_label (1, &menuitems[i]);
- }
- else if (mouse.event == M_EVENT_UP) {/* button up */
- if (oindex != -1) { /* If up in menu item. */
- if (i == oindex){ /* And same item down in. */
- *ch = menuitems[i].val; /* Return menu character. */
- rv = 1;
- }
- }
- }
- }
-
- /* If this is mouse up AND there was a mouse down in a menu item
- * then uninvert that menu item */
- if(mouse.event == M_EVENT_UP && oindex != -1)
- invert_label(0, &menuitems[oindex]); /* restore label */
-
- return(rv);
- }
-
-
- /*
- * invert_label - highlight the label of the given menu item.
- */
- void
- invert_label(state, m)
- int state;
- MENUITEM *m;
- {
- int i, j, r, c, p;
- char *lp;
- int old_state;
- int wasShown;
- int col_offset;
-
- if(m->val == mnoop)
- return;
-
-
- mswin_getpos (&r, &c); /* get cursor position */
- wasShown = mswin_showcursor (0);
- old_state = mswin_getrevstate ();
- /*
- * Leave the command name bold
- */
- col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label);
- (*term.t_move)(m->tl.r, m->tl.c + col_offset);
- (*term.t_rev)(state);
-
- for(i = m->tl.r; i <= m->br.r; i++) {
- for(j = m->tl.c + col_offset; j <= m->br.c; j++) {
- if(i == m->lbl.r && j == m->lbl.c + col_offset){ /* show label?? */
- lp = m->label + col_offset;
- while(*lp && j++ < m->br.c)
- (*term.t_putchar)(*lp++);
-
- continue;
- }
- else
- (*term.t_putchar)(' ');
- }
- }
-
- (*term.t_rev)(old_state);
- mswin_move (r, c);
- mswin_showcursor (wasShown);
- }
- #endif /* MOUSE */
-
-
-
- /*
- * Called by mswin to scroll text in window in responce to the scrollbar.
- *
- * Args: cmd - what type of scroll operation.
- * scroll_pos - paramter for operation.
- * used as position for SCROLL_TO operation.
- *
- * Returns: TRUE - did the scroll operation.
- * FALSE - was not able to do the scroll operation.
- */
- int
- pico_scroll_callback (cmd, scroll_pos)
- int cmd;
- long scroll_pos;
- {
- switch (cmd) {
- case MSWIN_KEY_SCROLLUPLINE:
- scrollupline (0, 1);
- break;
-
- case MSWIN_KEY_SCROLLDOWNLINE:
- scrolldownline (0, 1);
- break;
-
- case MSWIN_KEY_SCROLLUPPAGE:
- backpage (0, 1);
- break;
-
- case MSWIN_KEY_SCROLLDOWNPAGE:
- forwpage (0, 1);
- break;
-
- case MSWIN_KEY_SCROLLTO:
- scrollto (0, 0);
- break;
- }
-
- update ();
- return (TRUE);
- }
-
-
-
- /*
- * Update the scroll range and position. (exported)
- *
- * This is where curbp->b_linecnt is really managed. With out this function
- * to count the number of lines when needed curbp->b_linecnt will never
- * really be correct. BUT, this function is only compiled into the
- * windows version, so b_linecnt will only ever be right in the windows
- * version. OK for now because that is the only version that
- * looks at b_linecnt.
- */
- update_scroll ()
- {
- long scr_pos;
- long scr_range;
- LINE *lp;
- static LINE *last_top_line = NULL;
- static long last_scroll_pos = -1;
-
-
- if (ComposerEditing) {
- /* Editing header - don't allow scroll bars. */
- mswin_setscrollrange (0);
- return(0);
- }
-
-
- /*
- * Count the number of lines in the current bufer. Done when:
- *
- * when told to recount: curbp->b_linecnt == -1
- * when the top line changed: curwp->w_linep != last_top_line
- * when we don't know the scroll pos: last_scroll_pos == -1
- *
- * The first line in the list is a "place holder" line and is not
- * counted. The list is circular, when we return the to place
- * holder we have reached the end.
- */
- if(curbp->b_linecnt == -1 || curwp->w_linep != last_top_line
- || last_scroll_pos == -1) {
- scr_range = 0;
- scr_pos = 0;
- for (lp = lforw (curbp->b_linep); lp != curbp->b_linep;
- lp = lforw (lp)) {
- if (lp == curwp->w_linep)
- scr_pos = scr_range;
-
- ++scr_range;
- }
-
- curbp->b_linecnt = scr_range;
- last_scroll_pos = scr_pos;
- last_top_line = curwp->w_linep;
- }
-
- /*
- * Set new scroll range and position.
- */
- mswin_setscrollrange (curbp->b_linecnt - 1);
- mswin_setscrollpos (last_scroll_pos);
- return (0);
- }
-
-
-
-
- /*
- * alt_editor - fork off an alternate editor for mail message composition
- *
- */
- int
- alt_editor(int f, int n)
- {
- char eb[NLINE]; /* buf holding edit command */
- char *fn; /* tmp holder for file name */
- char errbuf[128];
- char *writetmp();
- int status;
- int done;
- int rc;
-
-
- if(Pmaster == NULL)
- return(-1);
-
- if(gmode&MDSCUR){
- emlwrite("Alternate editor not available in restricted mode", NULL);
- return(-1);
- }
-
- if(Pmaster->alt_ed == NULL){
- if(!(gmode&MDADVN)){
- emlwrite("\007Unknown Command",NULL);
- return(-1);
- }
-
- /* Guess which editor they want. */
- if(getenv("EDITOR"))
- strcpy(eb, (char *)getenv("EDITOR"));
- else
- *eb = '\0';
-
- done = FALSE;
- while(!done){
- rc = mlreplyd("Which alternate editor ? ",eb,NLINE,QDEFLT,NULL);
-
- switch(rc){
- case ABORT:
- return(-1);
- case HELPCH:
- emlwrite("no alternate editor help yet", NULL);
-
- /* take sleep and break out after there's help */
- sleep(3);
- break;
- case (CTRL|'L'):
- sgarbf = TRUE;
- update();
- break;
- case TRUE:
- case FALSE: /* does editor exist ? */
- if(*eb == '\0'){ /* leave silently? */
- mlerase();
- return(-1);
- }
-
- done++;
- break;
- default:
- break;
- }
- }
- }
- else
- strcpy(eb, Pmaster->alt_ed);
-
- if((fn=writetmp(0, 1)) == NULL){ /* get temp file */
- emlwrite("Problem writing temp file for alt editor", NULL);
- return(-1);
- }
-
- strcat(eb, " ");
- strcat(eb, fn);
-
- emlwrite("Waiting for alternate editor to finish...", NULL);
-
- status = mswin_exec_and_wait ("alternate editor", eb);
-
- switch (status) {
-
- case 0:
- /*
- * Success: replace edited text with new text
- */
- curbp->b_flag &= ~BFCHG; /* make sure old text gets blasted */
- readin(fn, 0); /* read new text overwriting old */
- unlink(fn); /* blast temp file */
- curbp->b_flag |= BFCHG; /* mark dirty for packbuf() */
- ttopen(); /* reset the signals */
- refresh(0, 1); /* redraw */
- return(0);
-
-
- /*
- * Possible errors.
- */
- case -1:
- /* Failed to map return from WinExec to a HTASK. */
- emlwrite("Problem finding alternet editor task handle.", NULL);
- return (-1);
-
- case -2:
- /* User decided to abandon the alternate editor.*/
- emlwrite("Alternate editor abandoned.", NULL);
- return (-1);
-
- default:
- mswin_exec_err_msg ("alternate editor", status, errbuf, 128);
- emlwrite (errbuf, NULL);
- return (-1);
- }
- return (-1);
- }
-
-
- /*
- *
- */
- void
- pico_config_menu_items (KEYMENU *keymenu)
- {
- int i;
- KEYMENU *k;
- int key;
- char cleanLabel[64];
- char *rb;
-
- mswin_menuitemclear ();
-
- /* keymenu's seem to be hardcoded at 12 entries. */
- for (i = 0, k = keymenu; i < 12; ++i, ++k) {
- if (k->name != NULL && k->label != NULL &&
- k->menuitem != KS_NONE) {
-
- if (k->name[0] == '^')
- key = CTRL | k->name[1];
- else if (strcmp(k->name, "Ret") == 0)
- key = '\r';
- else
- key = k->name[0];
-
- if (k->label[0] == '[' && strchr (k->label, ']') != NULL) {
- strcpy (cleanLabel, &k->label[1]);
- rb = strchr (cleanLabel, ']');
- *rb = '\0';
- mswin_menuitemadd (key, cleanLabel, k->menuitem, 0);
- }
- else
- mswin_menuitemadd (key, k->label, k->menuitem, 0);
- }
- }
- }
-
-
- /*
- * bktoshell - suspend and wait to be woken up
- *
- * NOTE: Not yet used under WINDOWS.
- */
- int
- bktoshell()
- {
- return (0);
- }
-
-
- /*
- * P_open - run the given command in a sub-shell returning a file pointer
- * from which to read the output
- *
- * note:
- * For OS's other than unix, you will have to rewrite this function.
- * Hopefully it'll be easy to exec the command into a temporary file,
- * and return a file pointer to that opened file or something.
- *
- * xxx Need to figure out how to do this in windows.
- */
- FILE *P_open(c)
- char *c;
- {
- return (NULL);
- }
-
-
- /*
- * P_close - close the given descriptor
- *
- */
- P_close(fp)
- FILE *fp;
- {
- }
-
-
-
-
- /*
- * pico_file_browse - Exported version of FileBrowse below.
- */
- pico_file_browse(pdata, dir, fn, sz, flags)
- PICO *pdata;
- char *dir, *fn, *sz;
- int flags;
- {
- return(FileBrowse(dir, fn, sz, flags));
- }
-
-
-
-
-
-
-
- /*
- * FileBrowse - display contents of given directory dir
- *
- * intput:
- * dir points to initial dir to browse.
- * fn initial file name.
- * flags
- *
- * returns:
- * dir points to currently selected directory (without
- * trailing seperator character).
- * fn points to currently selected file
- * sz points to size of file if ptr passed was non-NULL
- *
- * 1 if a file's been selected
- * 0 if no files seleted
- * -1 if there where problems
- */
- FileBrowse(dir, fn, sz, flags)
- char *dir, *fn, *sz; /* dir, name and optional size */
- int flags;
- {
- struct stat sbuf;
- int rc;
- char lfn[NFILEN];
-
- if (flags & FB_SAVE) {
- rc = mswin_savefile (dir, fn, NFILEN);
- }
- else {
- *fn = '\0'; /* No initial file names for
- * open. */
- rc = mswin_openfile (dir, fn, NFILEN);
- }
- if (rc == 0) {
- if (sz != NULL) {
- /* build full path to stat file. */
- strcpy (lfn, dir);
- strcat (lfn, S_FILESEP);
- strcat (lfn, fn);
- if (stat (fn, &sbuf) < 0)
- strcpy (sz, "0");
- else
- strcpy (sz, prettysz (sbuf.st_size));
- }
- return (1);
- }
- return (0);
- }
-
-
-
- ResizeBrowser ()
- {
- return (0);
- }
-