ThesaSrc: zwndproc -- message handle for Thesa

See Example of stack trace and

See (ThesaHelp: buy the source for Thesa)

;zwndproc.lst
;Copyright (C) 2002 C. Bradford Barber.  All rights reserved.
;$Id: //product/thesa.com/main/src/zwndproc.htm#2 $
;$DateTime: 2002/08/10 21:28:43 $$Change: 65 $$Author: bbarber $
	include all.sym
codew	segment 
	PUBLIC wndproc

 ;;filter Messages for main Window
 ;
 ;   	proc hwnd:WORD,wmsg:WORD, wparam:WORD, lparam:DWORD
 ;	lasttime= cpu time of wm_timer message
 ;returns:
 ;	DX:AX= depends on wmsg
 ;	DS,ES destroyed
 ;      calls defwndproc by default (MSDN Win3.1 SDK 0.2.13)
 ;notes:
 ;	see below (wndproc) for message handling
 ;	must trap all errors
 ;
 ;	Current .crnoupdate= true if don't update the display
 ;
 ;group: sys.-windows
 ; call: zpurna initwin and Windows routines that call wndproc
 ; xref: zerrordlg

wndproc proc far
  stackdef <0>,<>
  aa@lparam = dword ptr argpas.word0
  aa@wparam = word  ptr argpas.word2
  aa@wmsg   = word  ptr argpas.word3 
  aa@hwnd   = word  ptr argpas.word4
  aa@argcnt = word5
  pushm	si,di,ds
  mov	ax,[bp].aa@hwnd		;;case of MessageId
  mov	bx,[bp].aa@wmsg
  mov	cx,[bp].aa@wparam
  mov	si,[bp].aa@lparam.se
  mov	di,[bp].aa@lparam.of
 ;  proclogx ,,'wndproc (zwndproc): hwnd @ax.hex msg @bx.hex wparam @cx.hex lparam @si.hex.di.hex'
  mov	ds,ss:curdataseg
  cmp	bx,wm_destroy
  mov	dx,'de'
  je	aa@wndprocx
  test	ss:curflags,crexitprogram ;;.{{InExitProgram
  jnz	aa@defwndprocx		;;..default processing of Message
  FIXUP ;should message processing depend on msgdepth? instead of dlgdepth etc.?
  test	ss:errinit,true		;;default processing unless ErrorInitialized
  jz	aa@defwndprocx		;;  and Current .display .initialized
  cmp	ss:curdisplay,sgnoref	;;  and Current .display .isValid
  je	aa@defwndprocx
  test	ss:sysinit,true		;;  and Current .systemInit
  FIXUP ;default processing locks everything out.  Now needs errinit, curdisplay, and sysinit
  jz	aa@defwndprocx
  mov	es,ss:curdisplay
  test	es:diflags,dinotvalid+dicheckerr
  jnz	aa@defwndprocx
  cmp	bx,wm_changecbchain
  mov	dx,'cb'
  je	aa@wndprocx
  cmp	bx,wm_close
  mov	dx,'cl'
  je	aa@wndprocx
  cmp	bx,wm_create
  mov	dx,'cr'
  je	aa@wndprocx
  cmp	bx,wm_drawclipboard
  mov	dx,'dr'
  je	aa@wndprocx
  cmp	bx,wm_mouseactivate
  mov	dx,'ma'
  je	aa@wndprocx
  cmp	bx,wm_queryendsession
  mov	dx,'qe'
  je	aa@wndprocx
  cmp	bx,wm_initmenu ;needed for cxignorebutton during zhancontext
  mov	dx,'im' 
  je	aa@wndproc
  cmp	bx,wm_killfocus
  mov	dx,'kf'
  je	aa@wndprocx
  cmp	bx,wm_paint		;;process paint {clears screen on inErrorDialog) 
  mov	dx,'pt'
  je	aa@wndprocx
  cmp	bx,th_basefocus
  mov	dx,'s2'
  je	aa@wndprocx
  cmp	bx,wm_setfocus
  mov	dx,'sf'
  je	aa@wndprocx
  FIXUP ;shouldn't setfocus be for all?
  cmp	ss:dlgdepth,0		;;if Current .dialogDepth
  je	aa@notdialog
  cmp	bx,wm_setcursor		;;.if Message = .setCursor
  jne	aa@notup2
  cmp	si,wm_lbuttonup		;;  and Message .mouseMessage = .leftButtonUp
  mov	dx,'su'	
  je	aa@wndprocx		;;..process set_cursor.up
aa@notup2:
  jmp	aa@defwndproc		;;.default processing
  FIXUP ;if curdata undefined then get an error 
aa@notdialog:
  cmp	bx,ds:ufindmsg
  mov	dx,'fi'			;FindText from hwins
  je	aa@wndprocx
  cmp	ax,ds:hwins		;;default processing if SubWindows
  je	aa@defwndprocx
  cmp	ss:msgdepth,0		;;  or MessageDepth > 0
  ja	aa@defwndprocx
  cmp	bx,wm_char
  mov	dx,'ch'
  jne	aa@notch
  cmp	cx,chmaxcontrol		;;non-printables processed as 'kd'
  jbe	aa@defwndprocx
  cmp	cx,chmaxprint
  ja	aa@defwndprocx
  jmp	aa@wndproc
aa@notch:
  cmp	bx,wm_command
  mov	dx,'cm'
  je	aa@wndprocx
  cmp	bx,wm_compacting
  mov	dx,'cp'
  je	aa@wndprocx
  ;wm_endsession, 		;;.{{EndSession}}
				;;..do nothing, full save in wm_queryendsession
  cmp	bx,wm_erasebkgnd	;;.{{EraseBackground}}
  je	aa@retnonzero 		;;..return True {upddisplay handles erase}
  cmp	bx,wm_hscroll
  mov	dx,'hs'
  je	aa@wndprocx
  cmp	bx,wm_initmenupopup
  jne	aa@notpopup
  mov	dx,'ip'
  cmp	di,3
  je	aa@wndprocx
  cmp	di,5
  je	aa@wndprocx
  cmp	di,6
  je	aa@wndprocx
  cmp	di,7
  je	aa@wndprocx
aa@defwndprocx:
  jmp	aa@defwndproc
aa@notpopup:
  cmp	bx,wm_keydown
  jne	aa@notkeyd
  callz zvirtual ;all,>dl	;remove cnisstate keys from log
  cmp	dl,cnisstate
  mov	dx,'kd'
  je	aa@defwndproc
aa@wndprocx:
  jmp	aa@wndproc
aa@notkeyd:
  cmp	bx,wm_lbuttondblclk
  mov	dx,'ld'
  je	aa@wndprocx
  cmp	bx,wm_lbuttondown
  mov	dx,'lb'
  je	aa@wndprocx
  cmp	bx,wm_lbuttonup
  mov	dx,'lu'
  je	aa@wndproc
  cmp	bx,wm_menuchar
  mov	dx,'mc' 
  je	aa@wndprocx
  cmp	bx,wm_mousemove
  jne	aa@notmove
  callz	zmousemove
  clear	ax
  clear	dx
  jmp	aa@ret1
aa@notmove:
  cmp	bx,wm_renderallformats
  mov	dx,'ra'
  je	aa@wndproc
  cmp	bx,wm_rbuttondblclk
  mov	dx,'rd'
  je	aa@wndproc
  cmp	bx,wm_rbuttondown
  mov	dx,'rb'
  je	aa@wndproc
  cmp	bx,wm_renderformat
  mov	dx,'rf'
  je	aa@wndproc
  cmp	bx,wm_rbuttonup
  mov	dx,'ru'
  je	aa@wndproc
  ;wm_setcursor is handled by wm_mousemove
  cmp	bx,wm_size
  mov	dx,'sz'
  je	aa@wndproc
  cmp	bx,wm_syscolorchange
  mov	dx,'cc'
  je	aa@wndproc
  cmp	bx,wm_syscommand
  jne	aa@notcmd
  mov	dx,'sc'
  push	cx
  and	cx,0fff0h
  cmp	cx,sc_minimize
  pop	cx
  jne	aa@notminimize
  cmp	ax,ds:hwnd
  je	aa@wndproc
aa@notminimize:
  jmp	aa@defwndproc
aa@notcmd:
  cmp	bx,wm_syskeydown
  jne	aa@notsys
  callz zvirtual ;all,>dl 
  cmp	dl,cnisstate
  je	aa@defwndproc
  mov	dx,'sd'
  cmp	cx,vk_f10
  je	aa@wndproc
  cmp	cx,vk_escape
  je	aa@wndproc
  test	si,sys_alternate2 ;alt-key
  jz	aa@defwndproc  ;key to minimized window
  pushm	ax,cx,di
  mov	al,cl
  ESsym	di,txtmenuchars		;;....default processing if .character in .menuChars
  mov	cl,es:[di].byte0
  clear	ch
  inc	di
  repne	scasb
  popm	di,cx,ax
  je	aa@defwndproc
  jmp	aa@wndproc
aa@notsys:
  cmp	bx,wm_timer		;;.{{Timer}}
  jne	aa@nottime
  cmp	cx,wstimerid		;;..exit if Message .timerId != .thesa
  jne	aa@defwndproc
  push	di
  push	cx
  op32				;;..Message .timerId <- classify 
  mov	di,ds:lasttime.low4	;;    lasttime >= looktime, nextmax, updtime
  op32
  cmp	di,ds:nextmax.low4
  mov	cx,3 
  NOTE  ;uses timerid
  jae	aa@wndtime  
  op32
  cmp	di,ds:looktime.low4
  mov	cx,1
  jae	aa@wndtime
  op32
  cmp	di,ds:updtime.low4
  mov	cx,2
  jae	aa@wndtime
  pop	cx
  pop	di
  jmp	aa@defwndproc
aa@wndtime:
  pop	di ;ignore cx (timeid)
  pop	di
  mov	dx,'ti'
  jmp	aa@wndproc  
aa@nottime:
aa@defwndproc:			;;.{{Default}}
  test	ss:testmode,true	;;..if TestMode
  jz	aa@nolog
  cmp	ss:dlgdepth,0		;;  and DialogDepth = 0 {otherwise lots of messages}
  jne	aa@nolog		;;...log request
  proclog ,,'zwndproc: defwindowproc hwnd @ax.hex msg @bx.hex wparam @cx.hex lparam @si.hex.di.hex'
aa@nolog:
  syswin defwindowproc, 
  jmp	aa@ret1
aa@retnonzero:
  clear	dx
  setnz ax
  jmp	aa@ret1
aa@wndproc:
  call	zwndproc ;xds,xes,xseg,>dx:ax
aa@ret1:
  popm	ds,di,si
  stackpop
  ret	aa@argcnt 
wndproc ENDP

;;handle windows Message
;
;	SS:BP,BX= Message (DH,DL= two-char code)
;	AX=   .hwnd
;	CX=   .wparam
;	SI:DI= .lparam
;	    EDI= CPU time for wm_timer
;	DS= curdataseg
;returns:
;	DX:AX= returned value for wmsg (normally 0)
;	clears ss:timecnt via ztimer
;	DS,ES destroyed
;	any segment may move
;notes:
;	see above for message filter
	FIXUP ;rewrite zwndproc to make messages look like commands
;	first call is wm_create from initwin
;	must trap all errors since called by Windows
;
;set crupdcells when:
;	curid changes (crnewcur, updcuritem, hanother)
;	need to reread data from disk (remdatas)
;	reset (handisplay, error, hanreset, chkwork repair)
;	update non-text, non-title cell (hancellcursor, hanother, nearcell)
;	also setid and repblank
;	VOK 1997/12
;
;group: sys.-windows
; call: initwin zpurna
; xref: zcommand e:\msvc\samples\defprocs\defwnd.c zerrordlg

	public zwndproc

zwndproc:
  dec	ss:inwindows ;called from DispatchMessage in zpurna ; before proccall since lots of time
  proccall ,,'zwndproc: process Message @bx.hex xx ''@dh.chr.dl.chr'' hwnd @ax.hex wparam @cx.hex (@cx.dec)\\lparam @si.hex.di.hex (@si.dec.di.dec)'
  stackdef <1>,
   aa@hwndax		equ word ptr zz@ax
   aa@msgid		equ word ptr zz@bx
   aa@wparamcx		equ word ptr zz@cx
   aa@lparamsi		equ word ptr zz@si
   aa@lparamdi		equ word ptr zz@di
  inc	ss:msgdepth		;;bump MessageDepth
  callz zlogstate ;all		;;log Thesa state
  cmp	bx,wm_setfocus		;;unless Command .isMouse or .setFocus
  je	aa@notignore
  cmp	bx,wm_killfocus
  je	aa@notignore
  cmp	bx,wm_paint
  je	aa@notignore		;;  or .paint or .killFocus
  cmp	bx,wm_mousefirst
  jb	aa@ignore
  cmp	bx,wm_mouselast
  jbe	aa@notignore
aa@ignore:
  and	ss:curxflags,not cxignorebutton ;;.clear Current .ignoreNextButtonClick
aa@notignore:
  clear	al			;;trap Errors in select of Command
  callf	traperr ;bx,cx,dx,bp
  jmp	aa@iferror
  nop
aa@errprogram:
  mov	ax,[bp].aa@hwndax
  mov	si,[bp].aa@lparamsi
  mov	di,[bp].aa@lparamdi
aa@notactivate:
  cmp	bx,wm_changecbchain ;'cb' ;;.{{ChangeClipboardViewerChain}}
  jne	aa@notchange
  VTEST ;ChangeClipboardViewerChain}}
  proclog ,<>,'zwndproc: change clipboard viewer chain'
  NOTE ;no errors, may be called during error processing
  cmp	cx,ds:hnextclip		;;..if Message .nextWindow = Current .nextClipboardViewer
  jne	aa@notnext
  mov	ds:hnextclip,di		;;...Current .nextClipboardViewer <- Message .newNextViewer
aa@notnext:
  mov	ax,ds:hnextclip		;;..unless Current .nextClipboardViewer .undefined
  ifzero ax
  jz	aa@nonext2
  syswin SendMessage  ;;...forward Message to Current .nextClipboardViewer
aa@nonext2:
  jmp	aa@ret0
aa@notchange:
  cmp	bx,wm_char	;'ch'	;;.{{Char}} 
  jne	aa@notchar
  mov	bl,cl
  clear bh
  cmp	bl,chmaxcontrol		;;..if Message .char .isNonPrintable
  jbe	aa@uni
  cmp	bl,chmaxprint
  jbe	aa@nothigh
a@uni:
  push	ds
  DSseg	ax,ansiuni		;;....WideCharacter <- AnsiToUnicode [Message.char]
  FIXUP ;lookup high codes in code page instead of ansidos
  sub	bl,80h
  twice	bx
  mov	bx,ds:ansiuni[bx]
  pop	ds
aa@nothigh:			;;...else
  clear	al			;;....WideCharacter <- Message .char
  callx	editcell		;;..apply WideCharacter to Current.cell
  jmp	aa@upd			;;..maybe update current data and cell
aa@notchar:
  cmp	bx,wm_close	;'cl'	;;.{{Close}} 
  jne	aa@notclose
  NOTE ;also called from zerrordlg
  cmp	ax,ds:hwnd		;;..if Message .window = MainWindow or SubWindows
  je	aa@hexit
  cmp	ax,ds:hwins
  jne	aa@nothexit
aa@hexit:
  test	ss:curflags,crexitprogram ;;...unless Current .exitprogram
  jnz	aa@exiting
  clear si			;;....unless exit program after updating
  cally	yexitprogram ;xds,xes
  jnc	aa@skipexit		;;.....exit function
aa@exiting:
  proclog ,<>,'hanexit: destroy base window'
  mov	ds,ss:curdataseg
  mov   ax,ds:hwnd
  syswin DestroyWindow  	;;...destroy MainWindow
  mov	ds,ss:curdataseg
  mov	ax,ds:hwins
  syswin DestroyWindow 	;;...destroy BaseWindow
aa@skipexit:
  jmp	aa@ret0			;;...return 0
aa@nothexit:
  mov	bx,ss:curhwnd		;;..if Message .window != Current .window
  cmp	ax,bx
  je	aa@closeok
  syswin SetFocus 		;;...set focus to Message .window
aa@closeok:
  callz	zhanclose		;;..close Current .window
  jmp	aa@upd			;;..maybe update current data and cell
aa@notclose:
  cmp	bx,wm_command	;'cm'	;;.{{Command}} 
  jne	aa@notcommand
  callz	zcommand 		;;..process Command
  jmp	aa@upd			;;..maybe update current cell
aa@notcommand:
  cmp	bx,wm_compacting	;;.{{Compacting}} 'cp'
  jne	aa@notcompact
  proclog ,<>,'zwndproc: compact memory for wm_compacting'
  FIXUP ;process wm_compacting to compact memory
  jmp	aa@ret0
aa@notcompact:
  cmp	bx,wm_create	;'cr'	;;.{{Create}} 
  jne	aa@notcreate
  NOTE ;wm_create changes the focus without wm_killfocus
  NOTE ;no MessageBox or DialogBox here, MSDN Q64329
  jmp	aa@ret0			;;..no nothing {used to get message into log}
aa@notcreate:
  cmp	bx,wm_destroy	;'de'	;;.{{Destroy}} 
  jne	aa@notdestroy
	public wmdestroy
wmdestroy:
  mov	cx,ss:curidwindow	;;..if Current .idWindow .defined and 
  jcxz	aa@noidwin
  mov	es,cx			;;  and Current .idWindow .handle = Message .handle
  cmp	es:wihwnd,ax
  jne	aa@noidwin
  mov	ss:curidwindow,sgnoref	;;...clear Current .idWindow
aa@noidwin:
  cmp	ax,ds:hwins		;;..if Message .window = .subWindows
  jne	aa@notquit
aa@quit:
  proclog ,<>,'zwndproc: post quit message'
  syswin postquitmessage,<0>	;;...post quit message to SysWindow
  clear	ax			;;...return 0
  jmp	aa@retax
aa@notquit:
  jmp	aa@zdefproc		;;..\else default processing
aa@notdestroy:
  cmp	bx,wm_drawclipboard ;'dr' ;;.{{DrawClipboard}}
  jne	aa@notdraw
  VTEST ;'zwndproc: draw clipboard after change' 
  NOTE ;no errors, may be called during error processing
  syswin GetClipboardOwner ;>ax ;;..if MainWindow != OwnerWindow for Clipboard
  cmp	ax,ds:hwnd
  je	aa@myclip
  proclog ,<>,'zwndproc: set windows clipboard for wm_drawclipboard'
  or	ss:curxflags,cxwinclip	;;...set Current .windowsClipboard
aa@myclip:
  mov	ax,ds:hnextclip		;;..unless Current .nextClipboardViewer .undefined
  ifzero ax
  jz	aa@nonext3
  syswin SendMessage  ;;...forward Message to Current .nextClipboardViewer
aa@nonext3:
  jmp	aa@ret0
aa@notdraw: 
  cmp	bx,ds:ufindmsg  ;'fi'	;;.{{FindMessage}}
  jne	aa@notfind		;;  [code from poppad3, Petzold 3.1, p. 476, see zhanfind]
  mov	ax,ds
  cmp	si,ax			;;..check segment to prevent seg faults
  je	aa@segok
  reterr <009c8h>,'zwndproc: find message uses segment @si.hex instead of @ax.hex'
aa@segok:
  mov	si,offset findbuf	;;..get FindBuf.size for FindBuf
  pushm	si
  callx	skipprint ;di,>si
  mov	cx,si
  pop	si
  sub	cx,si
  mov	ds:findsiz,cl
  mov	ax,[di].fr_flags.low4	;;..if FindMessage .exit
  test	ax,fr_dialogterm
  jz	aa@notterm
  proclog ,<>,'zwndproc: exit find dialog'
  mov	ds:hfinddlg,0		;;....clear FindDialog {end sends a wm_setfocus to hwins}
  jmp	aa@ret0
aa@notterm:			;;...else
  mov	di,ss:curscan
  test	ax,fr_down		;;....if FindMessage .downFlag
  mov	bx,cnfindnext		;;.....handle FindNext key at Current
  jnz	aa@find			;;....\else
  mov	bx,cnfindprev		;;.....handle FindPrev key at Current
aa@find:
  callx	zhanfind ;xds,xes
  mov	di,ss:curscan		;;..update Scan for Current {for zadjdisplay}
  mov	ds,ss:curdata
  mov	es,ss:curcell
  callz zupdscan
  FIXUP ;zhanfind needs zupdscan before BringWindowToTop so that upddisplay does updscroll correctly.  Rework!
  mov	ds,ss:curdataseg
  syswin BringWindowToTop  	;;..set active window to Current .curWindow
  NOTE ;does not invoke wm_killfocus [already top?], invokes wm_setfocus
  jmp	aa@upd			;;..maybe update
aa@notfind:
  cmp	bx,wm_hscroll	;'hs'	;;.{{HorizonalScroll}} 
  jne	aa@notscroll
  FIXUP ;process horizontal scroll
aa@ret0x:
  jmp	aa@ret0
aa@notscroll:
  cmp	bx,wm_initmenu  ;'im' 	;;.((Init_menu}}
  jne	aa@notmenu
  or	ss:curxflags,cxignorebutton ;;..set Current .ignoreNextButtonClick
IF 0
  NOTE  ;difficult to get dynamic menu bars
  mov	dx,ax			;;..if Window for Message .windowHandle
  push	dx ;hwnd
  callz	zdetwin ;>ds
  pop	si ;hwnd
  jnc	aa@gotmenu
  test	ds:wiflags,wimenu	;;  and not Window .hasMenu
  jnz	aa@gotmenu
  mov	es,ss:curdataseg	;;...attach MainMenu to Message .window
  syswin SetMenu  ;si,>ax
  NOTE  ;removed at next aa@upd
  ifzero ax
  jnz	aa@setok
  reterr <00989h>,'zwndproc: could not attach menu to window @si.hex.ds.window'
aa@setok:
  syswin DrawMenuBar  ;si	;;...draw menu bar for Message .window
  or	ds:wiflags,wimenu	;;...set Window .hasMenu
				;;...initiate key menu processing
  syswin DefWindowProc 
aa@gotmenu:
ENDIF
  jmp	aa@ret0			;;..do nothing
aa@notmenu:
  cmp	bx,wm_initmenupopup ;'ip' ;;.((Init_Popupmenu}}
  jne	aa@notpmenu
  ;inactive popups culled above
			 ;'ip' ;;.((Init_Popupmenu}}
  callz	zsetpopup ;xds,xes	;;..set up menu
  jmp	aa@ret0			;;..return 0
aa@notpmenu:
  cmp	bx,wm_keydown	;'kd'	;;.{{KeyDown, or SysKeyDown/alt}}
  je	aa@keydown
  cmp	bx,wm_syskeydown ;'sd'
  jne	aa@notdown2		;;..if SysKeyDown
  test	si,sys_alternate2	;;     and .alternateKey or not (F10 or Escape)
  jnz	aa@alt
  cmp	cx,vk_f10
  je	aa@keydown
  cmp	cx,vk_escape
  je	aa@keydown
aa@alt:
  push	cnisvirt ;.classification
  or	cx,cnvk+cnalt		;;....set VirtualChar .isVirtual and .isAlt
  jmp	aa@gotchar
aa@keydown:			;;...else
  callz zvirtual ;all,>dl	;;....get classification for virtual Key
  push	dx ;.classification	;;     {cnisstate culled above}
  or	cx,cnvk			;;....set VirtualChar .isVirtual
  push	cx			;;....if ShiftKey set
  syswin GetKeyState  ;>ax
  pop	cx
  test	ax,8000h
  jz	aa@notshift
  or	cx,cncap		;;.....set VirtualChar .shifted
aa@notshift:
  push	cx			;;....if ControlKey set
  syswin GetKeyState,vk_control ;>ax
  pop	cx
  test	ax,8000h
  jz	aa@notctl
  or	cx,cnctl		;;.....set VirtualChar .control
aa@notctl:
aa@gotchar:
  push	cx			;;..get CommandChar for Message .virtualKey
  mov	ax,cx
  callz zgetcmd ;>al,bx
  pop	cx
  pop	dx ;.classification
  ifzero bx			;;..if CommandChar .undefined
  jnz	aa@keyok
  test	cx,cnctl		;;...if VirtualChar .notControl and
  jnz	aa@keyerr
  cmp	dl,cnischar		;;  VirtualChar .classification .isChar or .isOem
  je	aa@zdefprocx
  cmp	dl,cnisoem
  jne	aa@keyerr
aa@zdefprocx:
  jmp	aa@zdefproc		;;....default processing
aa@keyerr:			;;...report error
  mov	ax,cx
  and	ax,not cncap+cnvk+cnctl+cnalt
  reterr <00542h>,'zwndproc: no command found for key @cx.hex class @dl.hexb with virtual code @ax.hex'
aa@keyok:
  callx	editcell ;xds,xes	;;..apply CommandChar to Current .cell 
  jmp	aa@upd			;;..maybe update current cell
aa@notdown2:
  cmp	bx,wm_killfocus	;'kf'	;;.{{KillFocus}}
  jne	aa@notkill
  NOTE  ;called on entry to error dialog from zenterdlg, no errors
  proclog ,,'zwndproc: destroy caret on wm_killFocus @ax.hex to @cx.hex' 
  mov	ss:hasfocus,false	;;..clear Current .hasFocus
  push	cx			;;..destroy caret
  syswin DestroyCaret <> 
  pop	dx			;;..NextFocus <- Message .nextFocus
  mov	cx,ss:curdisplay	;;..if Current .display .isDefined
  jcxz	aa@nodisplay
  mov	es,cx
  mov	es:dicarethwnd,0	;;...clear Current .display .caretHwnd
aa@nodisplay:
  cmp	ss:dlgdepth,0		;;..if DialogDepth .isZero
  jne	aa@sameapp
  test	ss:inerror,true		;;  and not .inError
  jnz	aa@sameapp
  ifzero dx			;;...if NextFocus .undefined or
  jz	aa@nofocus
  mov	al,ehnoreport		;;....trap Errors .withoutReporting in
  callf	traperr
  jmp	aa@iferrork
  nop
aa@errprogramk: ;dx,bp
				;;.....set NewApp
  clear	cx			;;.....for each Window in Display
aa@kfloop:	;CX= Count, DS= Window, DX= SysWindow, DI= .end
  callx	nextwindow ;dx,>ds,cx,di
  jnc	aa@kfexit
  cmp	dx,ds:wihwnd		;;......if Window .handle = NextWindow
  jne	aa@kfloop
  clear	dx			;;.......clear NewApp
aa@kfexit:			;;.......exit loop
  retf	;end of traperr
aa@iferrork:
  jc	aa@nofocus		;;....if error or NewApp
  ifzero dx
  jz	aa@sameapp
aa@nofocus:
  callx	upddcdx ;xseg		;;.....update DCD completely
aa@sameapp:
  jmp	aa@ret0			;;..return 0
aa@notkill:
  cmp	bx,wm_lbuttondown ;'lb'	;;.{{LeftButton}}
  jne	aa@notlbut
  test	ss:curxflags,cxignorebutton ;;..if Current .ignoreButton for set focus
  jnz	aa@ret0			;;..return 0
  or 	ss:curxflags,cxblockmode  ;;..set Current .blockMode
  jmp	aa@ret0			;;..return 0
aa@notlbut:
  cmp	bx,wm_lbuttondblclk ;'ld' ;;.{{LeftDoubleClick}}
  jne	aa@notdouble
aa@errdouble:			;;..report error
  reterr <00544h>,'zwndproc: double click is ignored'
  NOTE ;if sometimes allow double click, may want to avoid overhead of error handling
aa@notdouble:
  cmp	bx,wm_lbuttonup	;'lu'	;;.{{LeftButtonUp}}
  jne	aa@notup
  FIXUP ;should drags be ignored?
  and	ss:curxflags,not cxblockmode ;;..clear Current .blockMode
  test	ss:curxflags,cxignorebutton ;;..if Current .ignoreButton for set focus
  jnz	aa@ignoreb		;;...clear .ignoreButton, return0 and check update
  push	cx ;wparam
  callz zsetmouse ;>di,ds,es	;;..set Current.display .caret to Mouse .position
  pop	cx ;wparam
  mov	si,ss:[di].scposition	;;..if Current .scan .position = .endline
  cmp	si,ss:[di].scendline
  jne	aa@go
  je	aa@upd			;;....maybe update current cell
aa@go:
  and	cx,mk_control+mk_shift	;;...else if Mouse .controlShift = 0
  jnz	aa@leftflag
  VTEST ;variations on mouse control
  mov	ds,ss:curdata
  ; same: hangoto
  or	ss:[di].scflags,scsetid	;;....set Scan .setId
  setnz	al			;;....get ItemId for goto Scan .position
  callx	idtext ;xds,xes,xseg,>al,bx
  pushm	ax,bx ;ItemId
  mov	cx,ss:curidwindow 	;;....if Current .idWindow .defined
  jcxz	aa@notcur
  mov	ds,cx			;;.....make Current .idWindow current id
  callx	makecurrent
aa@notcur:
  popm	bx,ax
  callx	updcuritemx ;xseg,xds,xes ;;....update Current item to ItemId or its alias
  jmp	aa@upd			;;....maybe update current cell
aa@leftflag:
  cmp	cx,mk_shift		;;...else if Mouse .controlShift = .shift
  je	aa@upd			;;....maybe update current cell
				;;...else
aa@errbutton:			;;....report soft error
  reterr <00543h>,'zwndproc: use the left button for ''goto'', the right button for a menu, and the shift+left button for editing'
aa@notup:
  cmp	bx,wm_mouseactivate ;'ma' ;;.{{MouseActivate}}
  jne	aa@notmouseact
  cmp	di,htclient		;;..if Message .mouseHit = .client or .scroll
  je	aa@maignore
  cmp	di,hthscroll
  je	aa@maignore
  cmp	di,htvscroll
  jne	aa@manot
aa@maignore:
  test	ss:hasfocus,true	;;  and not Current .hasFocus
  jnz	aa@manot
  or	ss:curxflags,cxignorebutton ;;....ignore next mouse button
  mov	ax,ma_activate		;;....return Activate
	;wm_setfocus
  jmp	aa@retax
aa@manot:			;;...else
  NOTE  ;duplicated from wm_setfocus to avoid activating window on item click
	;  updcaret will call BringWindowToTop if needed
  mov	ds:curhwnd,ax		;;....Current .curWindow <- Message .window
  mov	ds:caretheight,0	;;....clear Current .caretHeight {updcaret recreates}
  mov	ax,ma_noactivate	;;....return NoActivate
  jmp	aa@retax		;;   {continues with button down or button up}
aa@notmouseact:
  cmp	bx,wm_menuchar  ;'mc'	;;.{{MenuChar}}
  jne	aa@notmenuc
  cmp	di,mf_popup		;;..if PopUp and TestMode
  jne	aa@noteq
  test	ss:testmode,true
  jz	aa@noteq
  NOTE 	;no easy way to determine menu handle of sub-menu (DI).  It is created
	; in zsetpopn which doesn't know which menu it is
				;;  and Message .char = '=' or '+'
  cmp	cl,'='			;;...if Message .char = '='
  mov	di,offset txttest	;;.....Title <- TestTitle
  je	aa@eq
  cmp	cl,'+'			;;....else if Message .char = '='
  mov	di,offset txttestlog	;;.....Title <- TestLog
  jne	aa@noteq
aa@eq:
  clear	bx			;;...get ItemId for Title, create if necessary
  callx	getitemtitle ;xseg,ds,>al,bx
  clear	dx ;_incmirror
  callx	updcuritemx ;xds,xes	;;...update Current .item to ItemId or its alias
  mov	dx,mnc_close2		;;...update current cell and return .closeMenu
  clear	ax
  jmp	aa@upd2		
aa@noteq:
  jmp	aa@ret0			;;..return 0
aa@notmenuc:
	;wm_mousemove   ;'mm'	;;.{{MouseMove with Current .blockMode}}
				;;..see zmousemove
  cmp	bx,wm_paint	;'pt'	;;.{{Paint}}
  jne	aa@notpaint
  callz	zwmpaint ;xds,xes	;;..process paint Message
  jmp	aa@ret0			;;..return 0 
aa@notpaint:
  cmp	bx,wm_queryendsession ;'qe' ;;.{{QueryEndSession}}
  jne	aa@notend
  NOTE ;Win95 calls this from inside getmessage instead of dispatchmessage
       ;  a non-zero AX return does not work.  It requires zdefproc for some reason
       ;  Next getmessage returns timer message.  Somewhere _hanerror fails
       ;  with a code 79, but everything seems to work out ok.
  clear	si			;;..if exit program after updating, do not exit
  cally	yexitprogram ;>C
  jc	aa@zdefproc		;;...perform default processing
  jmp	aa@ret0			;;..return 0
aa@notend:
  cmp	bx,wm_renderformat ;'rf' ;;.{{RenderFormat}}
  xchg	bx,si
  je	aa@rendertext		;;..render text
  cmp	si,wm_renderallformats ;'ra' ;;.{{RenderAllFormats}} {at end of process}
  jne	aa@notrenderall
  VTEST ;renderformat
  syswin OpenClipboard  ;si,>ax ;;..unless open clipboard for MainWindow
  ifzero ax
  jnz	aa@opened
  FIXUP ;render all formats on exitprogram
  proclog ,<>,'00553h wm_renderallformats (zwndproc): could not open clipboard.  Is it opened by another process?'
  jmp	aa@ret0			;;..exit after logging error 
aa@opened:
  syswin EmptyClipboard ;si,>ax	;;..unless empty clipboard
  ifzero ax
  jnz	aa@emptied
  proclog ,<>,'00554h wm_renderallformats (zwndproc): could not empty clipboard.'
  jmp	aa@ret0			;;..exit after logging error 
aa@emptied:
aa@rendertext:
  push	si ;Message
  clear	al			;;..trap Errors in
  callf	traperr
  jmp	aa@iferrorra
  nop
aa@errprogramra: ;bx,cx,dx,bp
  callz	zrendertext		;;....render text data for clipboard
  nop	;_incmirror
  retf	;end of traperr
aa@iferrorra: ;xds,xes		;;...ignore Errors
  pop	si ;Message		;;..if message = wm_renderallformats
  cmp	si,wm_renderallformats
  jne	aa@ret0
  syswin CloseClipboard		;;...close Clipboard, ignore errors
  jmp	aa@ret0			;;..return 0
aa@notrenderall:
  xchg	bx,si
  cmp	bx,wm_rbuttondown ;'rb'	;;.{{RightButtonDown}}
  jne	aa@notrbut
  jmp	aa@ret0			;;..return 0
aa@notrbut:
  cmp	bx,wm_rbuttondblclk ;'rd' ;;.{{RightDoubleClick}}
  jne	aa@notrdouble
  jmp	aa@errdouble		;;...report error since 'rb' message already processed
aa@notrdouble:
  cmp	bx,wm_rbuttonup   ;'ru'	;;.{{RightButtonUp}}
  jne	aa@notrup
  VTEST ;wm_rbuttonup   ;'ru'	;;.{{RightButtonUp}}
  test	ss:curxflags,cxignorebutton ;;..unless Current .ignoreButton for set focus
  jnz	aa@ignoreb		;;...clear .ignoreButton, return0 and check update
  and	cx,mk_shift+mk_control	;;...error if Mouse .shiftControl
  jnz	aa@errbutton
  callz zsetmouse ;>di,ds,es	;;...set Current.display .caret to Mouse .position
  mov	ds,ss:curdataseg	;;...display RightMenuId at Current
  mov	ax,ds:hsubright
  callz	zhancontext ;xds	
  jmp	aa@upd			;;...maybe update current cell
aa@ignoreb:
  and	ss:curxflags,not cxignorebutton
  jmp	aa@ret0
aa@notrup:
  cmp	bx,th_basefocus ;'s2'	;;.{{SetBaseFocus}}
  jne	aa@notbase2
  mov	di,ds:curhwnd		;;....Message .window <- Current .curWindow
  proclog ,,'zwndproc: convert wm_setfocus of base window to wm_setfocus of window @di.hex'
  syswin BringWindowToTop  ;di ;;....bring Current .curWindow to top
  NOTE ;maybe invokes wm_killfocus [not seen 7/02], invokes wm_setfocus
  jmp	aa@ret0			;;....return 0
aa@notbase2:
  cmp	bx,wm_setfocus	;'sf'	;;.{{SetFocus}} {see: KillFocus 'kf'}
  jne	aa@notsetfocus
  cmp	ax,ds:hwins		;;..if Message .window = BaseWindows
  jne	aa@notsetsub
  cmp	ss:dlgdepth,0		;;...if DialogDepth .isZero
  jne	aa@nottop
				;;....post SetBaseFocus to Message .window
  syswin PostMessage  
				;;  {otherwise hwins gets keystrokes}
aa@nottop:			
  jmp	aa@ret0			;;...return 0
aa@notsetsub:
  proclog ,,'zwndproc: set focus to Window @ax.hex'
  NOTE  ;duplicated by wm_mouseactivate if ss:hasfocus
  mov	ss:hasfocus,true	;;..set Current .hasFocus
  mov	ds:curhfocus,ax		;;..Current .curFocusWindow <- Message .window
  mov	ds:curhwnd,ax		;;..Current .curWindow <- Message .window
  mov	ds:caretheight,0	;;..clear Current .caretHeight {updcaret recreates}
  syswin InvalidateRect  ;;..invalidate Message .window {repaint}
  NOTE  ;can not report an error if exiting a dialog box
  cmp	ss:dlgdepth,0		;;..if DialogDepth .isZero
  jne	aa@skipcur
  and	ss:curflags,not crenddialog ;;..clear Current .endDialog
  callz	zsetcur ;xseg,>es	;;...set up current data, cell, scan, and window
				;;    for Current .display
aa@skipcur:
  jmp	aa@ret0
aa@notsetfocus:
  cmp	bx,wm_setcursor	;'su'	;;.{{SetCursor.up}}
  jne	aa@notsetcursor
  NOTE  ;only called if wm_lbuttonup during dialog
  syswin GetFocus <> ;>ax	;;..get FocusWindow
  ifzero ax			;;..if FocusWindow .undefined
  jz	aa@keepdlg
  mov	ax,ds:hdialog		;;...set focus to Current .dialogWindow
  proclog ,,'zwndproc: bring dialog window @ax.hex to top'
  syswin BringWindowToTop 	;;  {ignore errors}
aa@keepdlg:
  jmp	aa@ret0			;;..return 0
aa@notsetcursor:
  cmp	bx,wm_size	;'sz'	;;.{{Size}}
  jne	aa@notsize
  cmp	cx,SizeNormal		;;..if Message .sizeNormal or .sizeFullScreen
  je	aa@wmsize
  cmp	cx,SizeFullScreen
  jne	aa@notwmsize
aa@wmsize:
  mov	cx,ss:curdisplay	;; and Current .display .isValid
  jcxz	aa@notwmsize
  mov	ds,cx
  test	ds:diflags,dinotvalid+dicheckerr
  FIXUP ;currently always divalid by check at wndproc
  jnz	aa@notwmsize
  callz	zwmsize ;xds,xes	;;...change Depth and Width size for SysWindow
aa@notwmsize:
  jmp	aa@upd
aa@notsize:
  cmp	bx,wm_syscolorchange ;'cc' ;;.{{SystemColorChange}}
  jne	aa@notsyscolor
  syswin Ctl3dColorChange <>	;;..notify Ctl3d of color change
  jmp	aa@ret0
aa@notsyscolor:
  cmp	bx,wm_syscommand ;'sc'	;;.{{SystemCommand}}
  jne	aa@notsyscmd
  cmp	cx,sc_minimize		;;..if Message .command = .minimize {MainWindow)
  jne	aa@notminmain		;;....forward message to SubWindows
  cmp	ax,ds:hwnd
  jne	aa@notminmain
  proclog ,<>,'zwndproc: forward minimize of MainWindow to SubWindows'
  syswin DefWindowProc  ;>dx:ax
aa@notminmain:
  jmp	aa@retdxax
aa@notsyscmd:
  cmp	bx,wm_timer	;'ti'	;;.{{Timer}} ;only if nextmax, looktime, updtime
				;   EDI= Cputime
  jne	aa@nottimer
  mov	al,cl			;;..update Purna by TimerId (set above)
  callz	ztimer ;xds,xes
  jmp	aa@upd			;;....maybe update current cell
aa@nottimer:
  reterr <00954h>,'zwndproc: unknown Windows message @bx.hex.  Message is not cleared.  Check initial case statement.'
aa@upd:				;;maybe update cells by
  clear	ax			;;.clear Return
  clear	dx
  test	ss:curflags,crupdcells	;;.if Current .updateCells
				;	{crnewcur often set}
				;  (updcuritem getback hancellcursor 
				;  handisplay hanprevwork nearcell remdatas)
  jz	aa@noupd
aa@upd2:			;;..{here for update cells! with DX:AX= Return}
  pushm	ax,dx ;Return
  callz	zsetcur			;;..set up current data, cell, and window for 
  popm	dx,ax ;Return		;;     Current .display
aa@noupd:
  pushm	ax,dx ;Return
  mov	ds,ss:curwindow		;;.if Current .window .refType = .current
  cmp	ds:wireftype,clrefcur
  jne	bf@notrefcur
  mov	ss:curidwindow,ds	;;..Current .idWindow <- .window
aa@notrefcur:
  test	ss:curflags,crnoupdate	;;.unless Current .noUpdate
  FIXUP ;should crnoupdate be cleared in base errors?
  jnz	aa@noupdate
  callx	upddisplay ;xds,xes	;;...update Current_display
aa@noupdate:
  cmp	ss:msgdepth,1		;;..if MessageDepth = 1
  jne	aa@notbase
  cmp	[bp].aa@msgid,wm_timer 	;;...unless Message .id = .timer
  je	aa@notinit
  callz	zcktimer ;xds,xes,xseg	;;....check timer and initialize timeouts
  clear	ax ;_incmirror
aa@notinit:
  callx	chkbase ;xds,xes	;;...check DCD from base loop
  clear	ax ;_incmirror
aa@notbase:
  callz	ztestall ;xseg		;;..perform any additional tests
  inc	ss:progress		;;..bump Progress
  jnz	aa@nodec
  dec	ss:progress
aa@nodec:
  popm	dx,ax ;Return		;;..return Return
  jmp	aa@retdxax
aa@ret0:			;;.return 0 
  callz	ztestall ;xseg		;;  and perform any additional tests
  clear	ax	
aa@retax:
  clear dx
aa@retdxax:
  retf	;end of traperr
aa@zdefproc:			;;.or do default processing of Message
  mov	ax,[bp].aa@hwndax
  mov	bx,[bp].aa@msgid
  mov	cx,[bp].aa@wparamcx
  mov	si,[bp].aa@lparamsi
  mov	di,[bp].aa@lparamdi
  test	ss:testmode,true	;;..if TestMode
  jz	aa@nolog2
  cmp	ss:dlgdepth,0		;;  and DialogDepth = 0 {otherwise lots of messages}
  jne	aa@nolog2		;;...log request
  proclog ,,'zwndproc2: default processing for window @ax.hex command @bx.hex wparam @cx.hex lparam @si.hex.di.hex'
aa@nolog2:
  syswin defwindowproc, 
  retf	;end of traperr


aa@iferror: ;(NC) ax,dx (C) xds,xes,>di ;;.if Error
  jnc	aa@ret
  clear	ax		
  clear	dx
  test	ss:curxflags,cxhanerror ;;..if inside error handler
  jnz	aa@ret			;;...exit function normally
  cmp	ss:dlgdepth,0		;;..if DialogDepth .nonZero
  jne	aa@ret			;;...exit function normally
  cmp	ss:msgdepth,1		;;..if MessageDepth > 1
  ja	aa@ret			;;...exit function normally
  FIXUP ;is it correct to continue after errors in an embedded call?
  NOTE  ;allow error handling and zwndproc here, it appears to work ok
aa@errloop: ;xds,xes		;;..while Error during 
  clear	al			;;...trap Errors in
  callf traperr
  jmp	short aa@iferror2 ;xds,xes
  nop
aa@program2:
;  test	ss:curflags,crremerror	;;.....unless Error .wasSoft
;  jnz	aa@soft
  FIXUP ;removed crremerror optimization due to 10/9/00 error wedge, OK? remerror.err
  callx	resetcurrent ;xds,xes	;;......reset Current
  clear	ax ;_incmirror
  callx	chkbase ;xds,xes	;;......check DCD from base loop
  setnz al			;;.......check everything
  callx	ckall
  clear	ax ;_incmirror
  callz	zsetcur			;;......setup Current window and cell
aa@soft:
  test	ss:curflags,crnoupdate	;;.....unless Current .noUpdate
  FIXUP ;should crnoupdate be cleared in base errors?
  jnz	aa@noupdate2
  callx	upddisplay ;xds,xes	;;......update Current_display
aa@noupdate2:
  clear	al			;;.....update Purna by time .checkMaxDelay
  callz	ztimer ;xds,xes,xseg
  clear	ax			;;.....return 0
  clear	dx
  retf	;end of traperr
aa@iferror2: ;(NC) ax,dx (C) xds,xes ;;....if error
  jc	aa@errloop		;;.....repeat loop
aa@ret:
  cmp	ss:tcprecedence,piall	;;if Current .logAll
  jne	aa@notall
  callz	zlogstate ;all		;;.log Thesa state
aa@notall:
  dec	ss:msgdepth		;;decrement MessageDepth
  inc	ss:inwindows ;return to DispatchMessage in zpurna
  stackpop
  procret ,,'zwndproc'

codew	ENDS
	END