home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 3 Comm
/
03-Comm.zip
/
CKPM5X_S.ZIP
/
CKOPM4.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-27
|
43KB
|
1,280 lines
/******************************************************************************
File name: ckopm4.c Rev: 01 Date: 01-Apr-90 Programmer: C.P.Armstrong
File title: The Gpi window procedure and some associated functions.
Contents: GpiWndProc()
Modification History:
01 01-Apr-90 C.P.Armstrong created
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <process.h>
#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#define INCL_DOSERRORS /* For the block marking */
#define INCL_VIO /* and copying routines */
#define INCL_AVIO
#include <OS2.h>
#include "ckcker.h" /* For VT100 and TEKTRONIX */
#include "ckopm.h"
#include "ckorc.h" /* Resource defines */
/* Whoever thought up the defaults for GpiLoadFonts should be shot. The */
/* function wont look in the current directory and if an extension is */
/* supplied it wont look in the "libpath". If no path or extension is */
/* supplied it uses an extension of .DLL (all references in the refs. */
/* say to use .FON for font files). So there is no choice but to call */
/* ckofon.dll since I have no idea where users will want to keep the */
/* font files - presumably in the libpath somewhere. */
#define REPAINTSTACKSIZE 8192
#define FONFILE "ckofon"
/* Function definitions */
MRESULT EXPENTRY GpiWndProc(HWND,USHORT,MPARAM,MPARAM);
MRESULT EXPENTRY VioWndProc(HWND,USHORT,MPARAM,MPARAM);
void dbprintf(const char *,...);
int DecodePMChar(MPARAM,MPARAM);
void Put_cursor_onscreen(HWND,HVPS);
void TitleText(MPARAM,MPARAM);
int DoPMTekGin(HWND,USHORT*);
void avio_dispatch(struct avio_cellstr *, HVPS);
int menu_routine(HAB,HWND,HWND,HVPS,USHORT,MPARAM,MPARAM);
int init_menu(MPARAM,HWND,HWND,HAB);
/* Block marking and copying routiens */
int mouse_to_curpos(int,int,int *,int *,HVPS,HWND);
int do_mark(HWND,MPARAM,MPARAM,HVPS);
int end_mark(HWND,MPARAM,MPARAM,HVPS);
int start_mark(HWND,MPARAM,MPARAM,HVPS);
int range_reverse(int,int,int,int,int,HVPS);
int fill_clipboard(char far * ,int,HAB);
char * copy_block(int,int,int,int,HVPS);
int get_viops_size(int*,int*,HVPS);
void buff_strins(char *);
void far pc_paint_thread(struct pc_paint * pc_p);
void cdecl pm_err(char *); /* declared in ckopm.h. Redeclared here */
void cdecl pm_msg(char*,char*); /* to avoid having to include all the */
/* OS2.H stuff required for ckopm.h in an*/
/* attempt to beat the MSC5.1 out of heap*/
/* messages which occur for tiny files. */
void buff_insert(int);
/****** Initialised global variables */
char far * copyb=NULL; /* Paste buffer */
int far pasting=0;
char immediate_update=1; /* If 0 do not draw point now */
struct plot_command far pcroot= /* First plot command structure of */
{ /* linked list */
'\0',
0L,
0L,
NULL
};
static struct plot_command * pcurrent= /* Pointer to current plot command */
&pcroot; /* static makes it local to this file */
/**** Uninitialised global variables ****/
int pc_out; /* next value to be taken from the buffer */
int pc_in; /* next value to be inserted into the buffer */
/******************************************************************************
Function: GpiWndProc()
Description: Main routine which handle the messages sent to the window used
for Tek graphics
Syntax: MRESULT EXPENTRY GpiWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
Returns: Depends on the message
Mods: 01-Apr-90 C.P.Armstrong Well actually I created it ages ago.
Today is the day the "out of near heap"
error finally forced me to reduce the
no. of functions in ckopm1 to 3!!.
******************************************************************************/
MRESULT EXPENTRY GpiWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
{
extern HAB hab;
extern HWND hwndGFrame;
extern HWND hwndTFrame;
extern HVPS hvps;
extern ULONG wind_sem;
extern COLOR pmbgcol;
extern COLOR pmfgcol;
extern char defaultattribute;
extern char immediate_update;
extern char Vio_visible;
extern struct plot_command pcroot;
extern struct plot_command * pcurrent;
extern char minied; /* Indicates window is minimized */
extern ULONG paint_sem; /* Set when repaint desired */
extern ULONG stop_painting_sem; /* Set when about to clear */
extern int Term_mode;
static HPS gpi_hps;
static HPOINTER hptr; /* The cross pointer handle */
static HWND hwndMenu;
static struct pc_paint paintdat;
static struct fontstuff fs;
static int* repaintstk;
static TID repaintthrd;
HDC gpi_hdc;
RECTL rcl;
SIZEL sizl;
SWP swp;
POINTL ptl; /* Stores the next draw command coords */
QMSG qmsg;
static char c; /* contains the next draw command */
char far * psi; /* pointer to a string for graphic input string */
long rgbcol;
struct plot_command * pcc;
int i,start,x,y;
switch(msg)
{
case WM_CREATE:
gpi_hdc = WinOpenWindowDC(hwnd);
sizl.cx = sizl.cy = 0;
gpi_hps = GpiCreatePS(hab,gpi_hdc,&sizl, PU_PELS | GPIF_DEFAULT |
GPIT_MICRO | GPIA_ASSOC);
/* Load the menus */
hwndMenu = WinWindowFromID(
WinQueryWindow(hwnd,QW_PARENT,FALSE),
FID_MENU);
if(GpiLoadFonts(hab,FONFILE)!=GPI_OK)
{
pm_err("Failed to load TEKTRONIX fonts");
paintdat.fnt = NULL;
}
else
{
fs.name = "Tektronix";
fs.vect = 0;
fs.h = 8;
fs.w = 6;
/* Let paint thread access the font info */
paintdat.fnt = &fs;
/* Select the Tektronix font */
SelectFont(gpi_hps,LCID_TEKFONT,fs.name,fs.vect,fs.h,fs.w);
}
/* Load the mouse cross pointer */
hptr = WinLoadPointer(HWND_DESKTOP,(HMODULE)0,ID_CROSSPTR);
/* Start the paint thread - the font info is set up above */
DosSemClear(&(paintdat.StopPaintSem));
paintdat.root = &pcroot;
paintdat.hwnd = hwnd;
paintdat.fgcol = pmfgcol;
paintdat.bkcol = pmbgcol;
/* allocate stack for repaint thread */
if((repaintstk = (int*) malloc(REPAINTSTACKSIZE))==NULL)
{
dbprintf("Can't allocate paint_thread stack space\n");
DosExit(EXIT_PROCESS,1);
}
/* pc_paint_thread clears the EndPaintThread when its up and running */
if(DosSemSet(&(paintdat.EndPaintThread))!=0)
{
dbprintf("Can't set EndPaintThread\n");
DosExit(EXIT_PROCESS,1);
}
_beginthread(pc_paint_thread,repaintstk,REPAINTSTACKSIZE,&paintdat);
DosSemWait(&(paintdat.EndPaintThread),SEM_INDEFINITE_WAIT);
return(0);
case WM_COMMAND:
menu_routine(hab,hwndMenu,hwnd,hvps,msg,mp1,mp2);
break;
case WM_INITMENU:
init_menu(mp1,hwndMenu,hwnd,hab);
break;
case WM_SIZE:
/* Adjust VT100 screen to just fit new size if in VT100 mode */
if(Term_mode==VT100)
{
/* Size the Vio screen */
WinSetWindowPos(hwndTFrame,HWND_TOP,
0,0,
SHORT1FROMMP(mp2) , SHORT2FROMMP(mp2) ,
SWP_SIZE|SWP_MOVE);
}
else
{
WinQueryWindowPos(hwndTFrame,&swp);
swp.cy = SHORT2FROMMP(mp2)-swp.cy;
/* Set the position of the Vio window in the Gpi */
WinSetWindowPos(hwndTFrame,HWND_TOP,
(SHORT)swp.x,(SHORT)swp.cy,
(SHORT)0, (SHORT)0,
SWP_MOVE);
}
/* Reposition the current graphics position */
if(SHORT1FROMMP(mp1)!=0 && SHORT2FROMMP(mp1)!=0)
{
GpiQueryCurrentPosition(gpi_hps, &ptl);
ptl.x = ptl.x * (LONG)SHORT1FROMMP(mp2) / (LONG) SHORT1FROMMP(mp1);
ptl.y = ptl.y * (LONG)SHORT2FROMMP(mp2) / (LONG) SHORT2FROMMP(mp1);
GpiMove(gpi_hps, &ptl);
}
break; /* Now do the default for this window */
case WM_PAINT:
/* Stop repaint thread from painting */
if(DosSemWait(&(paintdat.StartPaintSem),SEM_IMMEDIATE_RETURN)==0)
{
DosSemSet(&(paintdat.StopPaintSem));
DosSemWait(&(paintdat.StopPaintSem),SEM_INDEFINITE_WAIT);
}
WinBeginPaint(hwnd,gpi_hps,NULL);
if(WinQueryWindowULong(WinQueryWindow(hwnd,QW_PARENT,FALSE),
QWL_STYLE) & WS_MINIMIZED)
{
minied=1;
WinSendMsg(hwndTFrame,WM_HIDE,(MPARAM)1L,(MPARAM)0L);
}
else
{
/* If we were minimized then show the text window */
if(minied)
{
WinSendMsg(hwndTFrame,WM_HIDE,0,0);
minied=0;
}
}
WinQueryWindowRect(hwnd,&rcl);
pmbgcol = VioToRgbColor((BYTE)(defaultattribute>>4));
pmfgcol = VioToRgbColor(defaultattribute);
/* Make sure the paint thread sees the current colours */
paintdat.fgcol = pmfgcol;
paintdat.bkcol = pmbgcol;
/* Make sure this PS knows the current fg colour */
GpiSetColor(gpi_hps,pmfgcol);
if(c!='v')
{
start = 0;
pc_out=pc_in;
WinFillRect(gpi_hps,&rcl,pmbgcol);
WinQueryWindowPos(hwnd,&(paintdat.pc_swp));
DosSemClear(&(paintdat.StartPaintSem));
}
c=0;
WinEndPaint(gpi_hps);
return(0);
case WM_USER:
/* Fill up the plot commands */
c = CHAR1FROMMP(mp2);
if(c=='c') /* Clear screen - we can deal with this here */
{
/* Tell the paint thread to stop */
DosSemClear(&(paintdat.StopPaintSem));
/* Free the malloc'd plot command areas */
pc_delete(&pcroot);
pcurrent=&pcroot;
ptl.x=0;
ptl.y=0;
/* Home the cursor */
GpiMove(gpi_hps,&ptl);
/* c=0 causes a screen clear */
c=0;
}
if(c==0 || c=='v')
{
WinQueryWindowRect(hwnd,&rcl);
WinInvalidateRect(hwnd,&rcl,TRUE);
}
else
{
/* Save the new plot command */
pcurrent = pc_save(pcurrent,mp1,mp2);
/* Most recent size is stored in the paintdat structure */
pc_interp(*pcurrent,&(paintdat.pc_swp),0,gpi_hps);
pc_in++;
}
return(0L);
case WM_GIN: /* Get coordinate of a mouse press */
WinPostMsg(hwndTFrame, WM_HIDE,mp1,mp1);
SetPMGinMode(hwnd,mp1,hptr); /* mp=1 set GIN mode, 0 clears it */
return(0L);
case WM_CHAR:
if(!(CHARMSG(&msg)->fs & KC_CHAR))
{
return(0);
}
case WM_BUTTON3DOWN:
case WM_BUTTON2DOWN:
case WM_BUTTON1DOWN:
if(DoPMTekGin(hwnd,&msg)) /* If we are in Gin mode then send */
return(0L); /* the waiting routine some coords */
/* else do the WinDefProc thing */
break;
case WM_MOUSEMOVE:
if(TestPMGinMode())
{
WinSetPointer(HWND_DESKTOP, hptr);
return((MRESULT)1);
}
break;
case WM_CLOSE: /* User clicked on "Close.." so give prog */
GpiDeleteSetId(gpi_hps,LCID_ALL); /* Delete all ids */
GpiUnloadFonts(hab,FONFILE); /* unload the kermit fonts */
break;
case WM_DESTROY:
GpiDestroyPS(gpi_hps);
return(0);
}
return(WinDefWindowProc(hwnd,msg,mp1,mp2));
}
/* Vector font stuff */
/******************************************************************************
Function: SelectFont()
Description: Creates and selects the font with the supplied name
Syntax: LONG SelectFont (hps,lcid ,szFacename, vect,h,w)
HPS hps
LONG lcid
CHAR *szFacename
int vect; It's a vector font
int h,w; Height and width of non-vector font
Returns:
Mods: 19-Jan-90 C.P.Armstrong Adapted from the PM Toolkit examples
05-Apr-90 C.P.Armstrong Selection of a vector font is optional
******************************************************************************/
LONG SelectFont (HPS hps, LONG lcid, CHAR *szFacename,
int vect,int h,int w)
{
FATTRS fat ;
fat.usRecordLength = sizeof fat ;
fat.fsSelection = 0 ;
fat.lMatch = 0 ;
fat.idRegistry = 0 ;
fat.usCodePage = GpiQueryCp (hps) ;
if(vect==0)
{
fat.lMaxBaselineExt = h ;
fat.lAveCharWidth = w ;
fat.fsType = 0 ;
fat.fsFontUse = 0 ;
}
else
{
fat.lMaxBaselineExt = 0 ;
fat.lAveCharWidth = 0 ;
fat.fsType = 0 ;
fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
FATTR_FONTUSE_TRANSFORMABLE ;
}
strcpy (fat.szFacename, szFacename) ;
if(GpiCreateLogFont (hps, NULL, lcid, &fat)!=2)
{
pm_err("Font not selected");
return(GPI_ERROR);
}
return(GpiSetCharSet(hps, lcid));
}
/******************************************************************************
Function: SetCharBox()
Description: Sets the character box size
Syntax: void setcharbox(hps,width,height)
HPS hps; Presentation space
int width; Width in PELS
int height; Height in PELS
Returns: nothing
Mods: 19-Jan-90 C.P.Armstrong created
******************************************************************************/
void SetCharBox(hps,width,height)
HPS hps;
int width; /* Width in PELS */
int height; /* Height in PELS */
{
SIZEF sizfx ;
sizfx.cx = MAKEFIXED(width,0);
sizfx.cy = MAKEFIXED(height,0);
GpiSetCharBox(hps,&sizfx);
return;
}
/******************************************************************************
Function: do_paste()
Description: Performs the "paste" operation. Transfers any text in the
clipboard to the keyboard input buffer.
Pauses after a CR to let kermit catch up!
Syntax: int do_paste(HAB hab)
Returns: 0 if successful
1 if not
Mods: 01-Apr-90 C.P.Armstrong created
02-Apr-90 C.P.Armstrong Filters out the LFs which cause problems
see * with the asshole VMS editors.
11-Apr-90 C.P.Armstrong Single LFs replace by CRs. Paste text
see ** from the OS/2 1.2 system editor causes
errors similar to those caused by LFs.
Function moved to ckopm4 as the addition
of two lines causes MSC5.1 to barf on
this function - even if two massive ones
are removed from ckopm3!!!!! Gimme
v6.00....... (for ever hopeful)
20-Apr-90 C.P.Armstrong Removed the wait after CR. Waiting
didn't help as PM couldn't process in-
coming text thus holding up the other
threads. The wait is now done in the
"conect" thread leaving PM free to
process incoming print messages.
* Turns out LFs are supplied by the vt100
routines when a CR is received and LF
alone causes a backspace with VMS
editors(!) resulting in long lines...
** The OS/2 system editor does not insert
CRs or LFs in wrap mode resulting in
very long lines which cause the VMS
editors to choke.
******************************************************************************/
do_paste(HAB hab)
{
extern char far * copyb;
extern int pasting;
int siz;
SEL sel;
char far * clipb;
if(copyb!=NULL) /* Copyb is allocated - pasting in progress */
return(-1);
if(!WinOpenClipbrd(hab)) /* Open the clipboard */
{
pm_err("Failed to open clipboard");
return(1);
}
copyb=NULL;
if( (sel = (SEL) WinQueryClipbrdData(hab,CF_TEXT)) )
{
clipb = MAKEP( sel,0 ); /* Convert selector to pointer to text */
siz = strlen(clipb)+1; /* Get length of text already there */
if( (copyb=malloc(siz))!=NULL)
{
strcpy(copyb,clipb); /* Copy clipboard text to buffer */
}
}
WinCloseClipbrd(hab); /* Close the clipboard */
/* If there was any text, and we copied it okay, copyb is not NULL */
if(copyb!=NULL) /* For Kermit simply put it into the */
{ /* keyboard buffer. */
pasting=1; /* Tell buff_empty we are using paste buf */
buff_insert(0); /* trigger buff_empty. */
}
return(0);
}
/******************************************************************************
Function: get_paste_char()
Description: Gets characters out of the paste buffer
Syntax: int get_paste_char()
Returns: The character or -1 if the buffer is empty
Mods: 24-Apr-90 C.P.Armstrong created
******************************************************************************/
int get_paste_char()
{
extern char far * copyb;
extern int pasting;
static int next=0;
char next_c;
if(copyb==NULL)
return(-1);
// if(next>0) /* Convert lone LFs to CRs */
// {
// if((copyb[next]==10) && (copyb[next-1]!=13))
// copyb[next]=13;
// }
if(copyb[next]==10) /* Skip the LF in CRLFs */
next++;
next_c=copyb[next];
if(next_c==0) /* If we've reached the end clean up */
{
next_c=-1;
next=0;
free(copyb);
pasting=0;
copyb=NULL;
}
else
next++;
return(next_c);
}
/* Requires INCL_DOSERRORS and INCL_VIO */
int mark_start_row; /* Start row of Vio marked block */
int mark_start_col; /* Start col of Vio marked block */
int mark_end_row; /* Start row of Vio marked block */
int mark_end_col; /* Start col of Vio marked block */
int marking; /* 0 if not marking, */
/* 1 if doing mark, */
/* 2 if block marked */
int direct; /* direction of marking */
int mcaptive; /* 1 if mouse is captured */
int start_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
{
extern int mark_start_row; /* Position of the start of the marked block */
extern int mark_start_col;
extern int mark_end_row;
extern int mark_end_start;
extern int marking;
extern int direct;
extern int mcaptive;
/* Unhighlight any current marked range */
direct=1;
if(marking==2)
range_reverse(mark_start_row,mark_start_col,mark_end_row,mark_end_col,
direct,hvps);
mouse_to_curpos(SHORT1FROMMP(mp1),SHORT2FROMMP(mp1),
&mark_start_row,&mark_start_col,hvps,hwnd);
mark_end_row = mark_start_row;
mark_end_col = mark_start_col;
direct=0;
marking = 1;
/* Capture the mouse */
WinSetCapture(HWND_DESKTOP,hwnd);
mcaptive=1;
return(0);
}
int end_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
{
extern int mark_end_row; /* Position of the end of the marked block */
extern int mark_end_col;
extern int marking;
int temp;
do_mark(hwnd,mp1,mp2,hvps);
/* Free up the mouse */
WinSetCapture(HWND_DESKTOP, NULL) ;
mcaptive=0;
if(mark_end_row==mark_start_row && mark_end_col==mark_start_col)
{
marking=0;
return(0);
}
/* Make sure point one is "higher" than point 2 */
if( ((mark_end_row==mark_start_row) && (mark_end_col<mark_start_col)) ||
(mark_end_row<mark_start_row) )
{
temp = mark_end_row;
mark_end_row = mark_start_row;
mark_start_row = temp;
temp = mark_end_col;
mark_end_col = mark_start_col;
mark_start_col = temp;
}
marking = 2;
return(0);
}
int quit_mark(HWND hwnd,MPARAM mp1, MPARAM mp2,HVPS hvps, HAB hab)
{
extern int marking;
if(marking!=0)
{
end_mark(hwnd,mp1,mp2,hvps);
do_copy(0,hvps,hab);
}
return(0);
}
/******************************************************************************
Function: do_mark()
Description: Marks an area of screen according to the mouse position.
Syntax: int do_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
Returns: 0
Mods: 01-Apr-90 C.P.Armstrong created
******************************************************************************/
int do_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
{
extern int mark_start_row; /* Position of the start of the marked block */
extern int mark_start_col;
extern int mark_end_row;
extern int mark_end_col;
extern int marking;
extern int direct;
int currow,curcol,temp; /* Current cursor position */
int atsrow,atscol,atecol,aterow;
int newdirect;
int wasa,nowa;
int diroff; /* Another fudge factor. Having marked forwards and are now
marking back must not rehighlite current chart until we pass
the orig place! */
if(marking!=1) /* Not marking a block! */
return(0);
mouse_to_curpos(SHORT1FROMMP(mp1),SHORT2FROMMP(mp1),
&currow,&curcol,hvps,hwnd);
/* Has cursor moved a character position */
if( (currow==mark_end_row) && (curcol==mark_end_col) )
return(0);
if( ((currow==mark_end_row) && (curcol<=mark_end_col)) ||
(currow<mark_end_row) )
newdirect = -1;
else
newdirect = 1;
/* are we above the start */
if( (currow==mark_start_row && curcol<mark_start_col)
|| currow<mark_start_row )
nowa=1;
else
nowa=0;
/* Were we above the start */
if( (mark_end_col<mark_start_col && mark_end_row==mark_start_row)
|| mark_end_row<mark_start_row)
wasa=1;
else
wasa=0;
/* Avoid having the start char erased in a move from above to below start */
/* or a move from below to above */
/* this is a real kludge. It double highlights the initial pos, leaving */
/* it the same! */
if(wasa!=nowa && direct!=0)
{
range_reverse(mark_start_row,mark_start_col,mark_start_row,mark_start_col,
1,hvps);
}
if( (nowa && (!wasa) && direct!=0) ||
((!nowa) && wasa && direct!=0))
diroff=0;
else if(nowa && newdirect==1 && direct!=0) /* above, going forward */
diroff=-1;
else if((!nowa) && newdirect==-1 && direct!=0)/* below, going back */
diroff=1;
else if(direct!=0)
{
mark_end_col+=newdirect;
diroff=0;
}
else
{
diroff=0;
}
direct=newdirect;
/* Do mainmark! */
range_reverse(mark_end_row,mark_end_col,currow,curcol+diroff,direct,hvps);
/* Update the previous position */
mark_end_col = curcol;
mark_end_row = currow;
/* If back at orig pos, make sure it gets highlit if cursor is moved */
/* Now needs to be specifically unhighlighted as well */
if( (mark_start_row==mark_end_row) && (mark_start_col==mark_end_col) )
{
range_reverse(mark_start_row,mark_start_col,mark_start_row,mark_start_col,
1,hvps);
direct=0;
}
return(0);
}
/*
Mode = 0 - Erase marked block - do not copy it
Mode = 1 - If block marked then clear clipboard, copy marked block to it
Mode = 2 - If block marked then append marked block to any text present
*/
do_copy(int mode, HVPS hvps, HAB hab)
{
extern int mark_start_row; /* Position of the start of the marked block */
extern int mark_start_col;
extern int mark_end_row;
extern int mark_end_col;
extern int marking;
char far * block;
if(mode>0)
{
if(marking!=2)
return(0);
/* Get the marked block */
if( (block = copy_block(mark_start_row,mark_start_col,
mark_end_row,mark_end_col,hvps)) !=NULL)
{
fill_clipboard(block,mode,hab);
}
}
/* Un mark the block */
range_reverse(mark_start_row,mark_start_col,mark_end_row,mark_end_col,
1,hvps);
marking=0;
return(0);
}
/******************************************************************************
Function: copy_block()
Description: Copies the defined Vio block to the clipboard in text format
only. If mode is 0 the previous contents are deleted. If
mode is 1 then the copied block is appended to the existing
text in the clipboard.
Note the the block coords must have the start character coords
higher (nearer the top, above, to the left of etc.) the
end character coords.
This routine uses a CRLF sequence delimit lines. The PETZOLD
clipboard example requires CRLF to produce correct newlines
so I've chosen to use this as the "standard".... mainly because
it's what I'm using to test the copy_block function!
A pointer to the string block is now returned. This is not
sharable memory. It should be "free()"d after use as it is
allocated using malloc().
Syntax: char * copy_block(strow,stcol,enrow,encol,hvps)
int strow,stcol; First character in block
int enrow,encol; Last character in block
HVPS hvps; AVIO handle to vio screen.
Returns: NULL if an error occurs
Pointer to the NUL terminated string block.
Mods: 31-Mar-90 C.P.Armstrong created
01-Apr-90 C.P.Armstrong Returns pointer to string block.
******************************************************************************/
char * copy_block(strow,stcol,enrow,encol,hvps)
int strow,stcol; /* First character in block */
int enrow,encol; /* Last character in block */
HVPS hvps; /* AVIO handle to vio screen. */
{
int sw,sh; /* Vio screen dims */
char far * cblk; /* Area for the copied block */
USHORT off; /* offset into buffer */
USHORT get; /* no. chars to get/got */
USHORT siz; /* Size of copied block */
/* First get screen dims */
if(get_viops_size(&sw, &sh,hvps)!=0)
return(NULL);
/* Calc size of block in chars with all lines except last terminated by */
/* a CR and the whole block NUL terminated. */
if(enrow==strow)
siz = encol-stcol+2; /* No. chars plus NUL */
else
{
siz = ((enrow-strow-1)*(sw+2)); /* No. full lines and CRLFs */
siz += (sw-stcol+2); /* No. chars on first line + CRLF */
siz += (encol)+2; /* No. chars on last line plus NUL */
}
/* Malloc the block - return NULL if we can't */
if( (cblk = (char far *) malloc(siz))==NULL)
return(NULL);
/* Read the block a line at a time into cblk, inserting CRs at the end of */
/* all but the last line. */
if(enrow==strow) /* Less than one line is special case */
{
get = encol-stcol+1;
VioReadCharStr(cblk,&get,strow,stcol,hvps);
cblk[get]='\0';
}
else
{
/* First line */
get = sw-stcol;
VioReadCharStr(cblk,&get,strow,stcol,hvps);
off=0;
do
{
do /* Trim trailing blanks */
{
get--;
}while((cblk[off+get]==' ') && (get>0));
/* off+get now points to last character */
cblk[off + (++get)]=13; /* Terminate previous string */
cblk[off + (++get)]=10;
off += (get+1); /* Offset of next string in memory block*/
strow++; /* Next row */
get = (strow==enrow)? encol+1 : sw;
VioReadCharStr(&cblk[off],&get,strow,0,hvps);
}while(strow<enrow);
cblk[off+get]='\0'; /* Nul terminate the string */
}
return(cblk);
}
/******************************************************************************
Function: fill_clipboard()
Description: Transfers a block of marked text to the clipboard.
In mode 1 the existing clipboard data is erased.
In mode 2 the new text is added to at the end of any existing
text in the clipboard.
Syntax: int fill_clipboard(char far * block,int mode,HAB hab)
Returns: 0 for success
1 if an error occurs
Mods: 01-Apr-90 C.P.Armstrong created
******************************************************************************/
int fill_clipboard(char far * block,int mode,HAB hab)
{
SEL sel;
char far * clipb;
char far * cblk;
int siz;
if(!WinOpenClipbrd(hab)) /* Open the clipboard */
{
pm_err("Failed to open clipboard");
return(1);
}
siz=0;
clipb = NULL;
if(mode==2) /* Mode 2 = append */
{
if( (sel = (SEL) WinQueryClipbrdData(hab,CF_TEXT)) )
{
clipb = MAKEP( sel,0 ); /* Convert selector to pointer to text */
siz = strlen(clipb)+1; /* Get length of text alredy there */
}
}
/* Add size of new text */
siz += strlen(block)+1; /* Note, if appending the memory block */
/* will be 1 too big - but who cares! */
/* Allocate the shared seg to give to clipboard */
if(DosAllocSeg(siz, &sel, SEG_GIVEABLE)!=0)
{
WinCloseClipbrd(hab); /* Must close the clipboard */
return(1);
}
/* Convert shared segment selector to pointer */
cblk = MAKEP(sel,0);
cblk[0]=0;
/* If clipb has been set we should copy its text first */
if(clipb != NULL)
strcpy(cblk,clipb);
/* Now add in the new marked block */
strcat(cblk,block);
/* Free the marked block */
free(block);
/* Empty the clipboard */
if(!WinEmptyClipbrd(hab))
pm_err("Failed to empty clipboard");
/* Now set it to the new stuff */
if(!WinSetClipbrdData(hab, (ULONG) sel, CF_TEXT, CFI_SELECTOR))
pm_err("Failed to place data in clipboard");
if(!WinCloseClipbrd(hab)) /* Close clipboard */
{
pm_err(
"You've got real problems now\nWe failed to close the clipboard");
return(1);
}
return(0);
}
/******************************************************************************
Function: mouse_to_curpos()
Description: Converts a mouse position into a Vio row/col position. The
mosue position is relative to the bottom lefthand corner,
the row/col position is relative to the top left corner of
the video buffer. i.e. an Vio origin shift is taken into
account.
If the position is outside the window the row/col is adjusted
to be inside the window.
This function can be used with any window coord in pels.
Syntax: int mouse_to_curpos(mousex,mousey,prow,pcol,hvps,hwnd)
int mousex,mousey; Mouse window x and y pos
int * prow, * pcol; Returned vio cursor pos
HVPS hvps; handle to the Vio pres space
HWND hwnd; Handle to the window containing the PS
Returns: 0
Mods: 01-Apr-90 C.P.Armstrong created
******************************************************************************/
int mouse_to_curpos(mousex,mousey,prow,pcol,hvps,hwnd)
int mousex,mousey; /* Mouse window x and y pos */
int * prow, * pcol; /* Returned vio cursor pos */
HVPS hvps; /* handle to the Vio pres space */
HWND hwnd; /* Handle to the window containing the PS */
{
SIZEL sizl;
SWP swp;
HDC hdc;
/* Get Vio window size and offset within the frame window */
WinQueryWindowPos(hwnd,&swp);
/* Get the size in pixels of a character */
hdc = WinQueryWindowDC(hwnd);
DevQueryCaps(hdc, CAPS_CHAR_WIDTH, 2L, (PLONG) &sizl);
/* Check mouse is in the window */
if(mousey<0)
mousey=0;
else if(mousey>swp.cy)
mousey=swp.cy;
if(mousex<0)
mousex=0;
else if(mousex>swp.cx)
mousex=swp.cx;
/* Convert mouse pos to top right origin */
mousey = swp.cy - mousey;
/* Calculate mouse pos in row/cols */
mousex = mousex/ (int)sizl.cx;
mousey = mousey/ (int)sizl.cy;
/* Get the current origin for the Vio screen (top left row/col) */
VioGetOrg((PSHORT)prow,(PSHORT)pcol,hvps);
/* Add offset to mouse pos */
*prow = *prow + mousey;
*pcol = *pcol + mousex;
return(0);
}
int range_reverse(atsrow,atscol,aterow,atecol,direct,hvps)
int atsrow,atscol; /* Highest position to start from */
int aterow,atecol; /* Postion to go down to */
int direct; /* Forward or reverse marking */
HVPS hvps; /* Handle of screen PS */
{
extern int scrwidth; /* This is needed until we find a way of determining it */
int atsz;
unsigned char attbuf[3];
/* Make sure the last one gets highlit */
atecol+=direct;
do
{
atsz=2;
if(VioReadCellStr(attbuf,(PUSHORT)&atsz,atsrow,atscol,hvps)
==ERROR_VIO_COL)
{
atsrow+=direct;
atscol=(direct==1) ? 0 : scrwidth-1;
}
else
{
attbuf[3] = (attbuf[1] << 4) + (attbuf[1] >> 4);
attbuf[1] = attbuf[3];
if(VioWrtCellStr(attbuf,2,atsrow,atscol,hvps)!=0)
return(0);
atscol+=direct;
}
}while( (atscol!=atecol) || (atsrow!=aterow));
return(0);
}
/******************************************************************************
Function: get_viops_size()
Description: Determines the dimensions of a Vio screen. VioGetMode is
supposed to do this but it doesn't work with an AdvancedVIO
presentatoin space handle. This function uses the
VioReadCharStr() error messages to determine the screen size.
Syntax: int get_viops_size(width,height,hvps)
int* width;
int* height;
HVPS hvps;
Returns: 1 if an unexpected error occurs
0 if okay
Mods: 30-Mar-90 C.P.Armstrong created
******************************************************************************/
int get_viops_size(int* width, int* height,HVPS hvps)
{
USHORT row,col,sz;
USHORT err;
char attr;
row=1;
col=1;
/* Do the width first, step 2 at once for speed */
do
{
sz=1;
}while( (err=VioReadCharStr(&attr,&sz,row,col+=2,hvps))==0);
if(err!=ERROR_VIO_COL)
return(1);
sz=1;
col--;
/* See if we've gone 1 too far */
if(VioReadCharStr(&attr,&sz,row,col,hvps)!=0)
col--;
/* Now do the height */
do
{
sz=1;
}while( (err=VioReadCharStr(&attr,&sz,row+=2,col,hvps))==0);
if(err!=ERROR_VIO_ROW)
return(1);
sz=1;
row--;
/* See if we've gone 1 too far */
if(VioReadCharStr(&attr,&sz,row,col,hvps)!=0)
row--;
*width= ++col; /* We want no. of characters, not max positions */
*height= ++row;
return(0);
}
/******************************************************************************
Function: pc_paint_thread()
Description: The thread which does the painting for the Gpi window
Special situations of which this function must be told;
1 About to clear the plot list.
2 Want to do a repaint so stop any repaint in progress
3 Program ending.
Syntax: void far pc_paint_thread()
Returns: nothing
Mods: 13-Feb-90 C.P.Armstrong created
******************************************************************************/
void far pc_paint_thread(struct pc_paint * pc_p)
{
// extern ULONG paint_sem; /* Set when repaint desired */
// extern ULONG stop_painting_sem; /* Set when about to clear */
// extern SWP pc_swp;
// extern struct plot_command pcroot;
// extern char minied;
// extern HPS gpi_hps;
extern COLOR pmfgcol;
extern HWND hwndGraph;
HPS hps;
HAB painthab;
int count;
struct plot_command * pcc;
painthab=WinInitialize(0);
DosSemSet(&(pc_p->StartPaintSem)); /* Make sure semaphore is set before */
/* entering the loop */
/* Clear the EndPaintThread sem so caller knows we are running */
DosSemClear(&(pc_p->EndPaintThread));
while(TRUE)
{
/* Wait for it to repaint request */
DosSemWait(&(pc_p->StartPaintSem),SEM_INDEFINITE_WAIT);
hps = WinGetPS(pc_p->hwnd);
/* Set parameters for this incarnations of the PS */
GpiSetColor(hps,pc_p->fgcol);
if(pc_p->fnt != NULL)
{
SelectFont(hps, LCID_TEKFONT,
pc_p->fnt->name,pc_p->fnt->vect,pc_p->fnt->h,pc_p->fnt->w);
/* Size the font */
SetCharBox(hps,
MAXCHARWIDTH* pc_p->pc_swp.cx/MAXXRES,
MAXCHARHEIGHT* pc_p->pc_swp.cy/MAXYRES);
}
pcc=(pc_p->root); /* Do the painting */
count=0;
do
{
pc_interp(*pcc,&(pc_p->pc_swp),0,hps);
pcc = pcc->next;
}
while((pcc != NULL)
&& (DosSemWait(&(pc_p->StopPaintSem),SEM_IMMEDIATE_RETURN)==0));
WinReleasePS(hps);
DosSemSet(&(pc_p->StartPaintSem)); /* Reset it */
/* Set the StopPaint to ack that we've stopped */
if(DosSemClear(&(pc_p->StopPaintSem))!=0)
dbprintf("pc_paint_thread - Error clearing StopPaintSem\n");
dbprintf("Repainting finished\n");
}
dbprintf("pc_paint_thread finishing\n");
WinTerminate(painthab);
DosEnterCritSec();
DosSemClear(&(pc_p->EndPaintThread));
DosExit(EXIT_THREAD,0); /* This will also do a DosExitCritSec */
}