source: trunk/fspopup.c@ 82

Last change on this file since 82 was 82, checked in by Gregg Young, 10 years ago

This commit is to allow me acces to my bleeding edge code at warpstock. Don't build this commit unless you are very familiar with lswitcher. It will work but is not ready for prime time.

File size: 12.8 KB
Line 
1/*
2 * Copyright (C) 1997-2006 Andrei Los.
3 * This file is part of the lSwitcher source package.
4 * lSwitcher is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation, in version 2 as it comes in the
7 * "COPYING" file of the lSwitcher main distribution.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include "lswitch.h"
15#include "common.h"
16#include "fspopup.h"
17
18#include <string.h>
19#include <stdio.h>
20#include <process.h>
21#define __PMPRINTF__
22#include "PMPRINTF.H"
23
24#ifndef XWORKPLACE
25#define INCL_LOADEXCEPTQ
26#include "exceptq.h"
27#endif
28
29static HMONITOR hmonKbd = (HMONITOR) 0;
30static MONIN monInBuf = { 0 };
31static MONOUT monOutBuf = { 0 };
32
33VOID FSMonitor(VOID * plswData)
34{
35 static USHORT usCount;
36 static KEYPACKET keybuf;
37 ULONG ulPostCount;
38
39#ifndef XWORKPLACE
40 EXCEPTIONREGISTRATIONRECORD exRegRec;
41
42 LoadExceptq(&exRegRec, "", NULL);
43#endif
44
45 DosSetPrty(PRTYS_THREAD, PRTYC_TIMECRITICAL, +31, 0);
46
47 while (DosWaitEventSem(((PLSWDATA) plswData)->hevRunning, 0) ==
48 ERROR_TIMEOUT) {
49 usCount = sizeof(keybuf);
50 if (DosMonRead
51 ((PBYTE) & monInBuf, DCWW_WAIT, (PBYTE) & keybuf, &usCount))
52 break;
53 DosMonWrite((PBYTE) & monOutBuf, (PBYTE) & keybuf, usCount);
54
55/* keybuf.mnflags>>8 is the scan code; check for the Tab key release*/
56 if ((keybuf.cp.fsState >> 8) ==
57 (((PLSWDATA) plswData)->Settings.ucPopupHotKey == 1 ? 1 : 2)
58 && (keybuf.mnflags >> 8) == (SCAN_TAB | 0x80)) {
59 if (keybuf.cp.fsState & 3)
60 DosPostEventSem(((PLSWDATA) plswData)->hevShift);
61 else
62 DosResetEventSem(((PLSWDATA) plswData)->hevShift,
63 &ulPostCount);
64 DosPostEventSem(((PLSWDATA) plswData)->hevPopup);
65 break;
66 }
67 }
68#ifndef XWORKPLACE
69 UninstallExceptq(&exRegRec);
70#endif
71}
72
73VOID FSMonDispat(VOID * pParm)
74{
75 PLSWDATA plswData;
76 SEL selGSeg, selLSeg;
77 PGINFOSEG GSeg;
78 UCHAR ucCurrId = 0, ucId;
79 ULONG ulPostCount;
80 APIRET rc;
81#ifndef XWORKPLACE
82 EXCEPTIONREGISTRATIONRECORD exRegRec;
83
84 LoadExceptq(&exRegRec, "", NULL);
85#endif
86 DebugHereIAm();
87 plswData = (PLSWDATA) pParm;
88
89 DosGetInfoSeg(&selGSeg, &selLSeg);
90 GSeg = (PGINFOSEG) ((selGSeg & ~7) << 13);
91
92 if (DosCreateEventSem(SEMFSPOPUPNAME, &plswData->hevPopup, 0, 0)) {
93#ifndef XWORKPLACE
94 UninstallExceptq(&exRegRec);
95#endif
96 return;
97 }
98 if (DosCreateEventSem(SEMSHIFTNAME, &plswData->hevShift, 0, 0)) {
99#ifndef XWORKPLACE
100 UninstallExceptq(&exRegRec);
101#endif
102 return;
103 }
104 rc = DosRequestMutexSem(plswData->htmxFSMonDispatRunning, SEM_INDEFINITE_WAIT );
105 PmpfF(("Mon RequestMSem %i", rc));
106 while (DosWaitEventSem(plswData->hevRunning, 10L) == ERROR_TIMEOUT) {
107 /* if we popup in PM reset the semaphore and post a triggering message;
108 if we popup in FS create a thread which will monitor the keyboard and
109 display the popup menu, post the semaphore one more time so that we do
110 not accidentally create one more such thread because the first one didn't
111 have time to issue VioPopUp and thus change current FS session;
112 the semaphore will be reset when a keyboard monitor for this thread is
113 created */
114 if (DosWaitEventSem(plswData->hevPopup, 200L) == 0 &&
115 (DosQueryEventSem(plswData->hevPopup, &ulPostCount),
116 ulPostCount == 1)) {
117 if (plswData->Settings.bPMPopupInFS) {
118 DosQueryEventSem(plswData->hevShift, &ulPostCount);
119 WinPostMsg(plswData->hwndPopup, WM_COMMAND,
120 MPFROMSHORT(ulPostCount >
121 0 ? CMD_SCROLLLEFTFROMFS :
122 CMD_SCROLLRIGHTFROMFS),
123 MPFROM2SHORT(CMDSRC_OTHER, FALSE));
124 DosResetEventSem(plswData->hevPopup, &ulPostCount);
125 }
126 else {
127 DosPostEventSem(plswData->hevPopup);
128 plswData->itidFSMon =
129 _beginthread(FSPopUp, NULL, 0x4000, plswData);
130 }
131 }
132
133 if ((ucId = GSeg->sgCurrent) != ucCurrId) {
134 ucCurrId = ucId;
135 if (hmonKbd != 0) {
136 DosMonClose(hmonKbd);
137 hmonKbd = 0;
138 }
139
140 if (DosMonOpen("KBD$", &hmonKbd) == 0) {
141 monInBuf.cb = sizeof(MONIN);
142 monOutBuf.cb = sizeof(MONOUT);
143 if (DosMonReg
144 (hmonKbd, (PBYTE) & monInBuf, (PBYTE) & monOutBuf, 1,
145 ucCurrId) == 0) {
146 if (DosQueryEventSem(plswData->hevPopup, &ulPostCount),
147 ulPostCount == 0)
148 plswData->itidFSMon =
149 _beginthread(FSMonitor, NULL, 0x4000, plswData);
150 }
151 else {
152 DosMonClose(hmonKbd);
153 hmonKbd = 0;
154 }
155 }
156 else
157 hmonKbd = 0;
158 DosResetEventSem(plswData->hevPopup, &ulPostCount);
159 }
160
161 }
162 DosSleep(200);
163 if (hmonKbd != 0)
164 DosMonClose(hmonKbd);
165 DebugHereIAm();
166 DosReleaseMutexSem(plswData->htmxFSMonDispatRunning);
167#ifndef XWORKPLACE
168 UninstallExceptq(&exRegRec);
169#endif
170}
171
172/* this function returns the number of the item with given line number
173 counting from top in the popup menu */
174SHORT ItemNumFromLineNum(LSWDATA * plswData, USHORT usLineNum)
175{
176 SHORT item;
177
178 item = usLineNum + plswData->iShift +
179 (plswData->Settings.bScrollItems ? plswData->usCurrItem : 0) -
180 (min(MAXTEXTITEMS, plswData->usItems) - 1) / 2;
181
182 AdjustItem(item, plswData->usItems);
183 return item;
184}
185
186/* this thread monitors keyboard activity during the popup */
187VOID FSPopUp(VOID * pParm)
188{
189 static USHORT usCount;
190 static KEYPACKET keybuf;
191 UCHAR ucScan;
192 USHORT usCounter, usPopOpt;
193 ULONG ulPostCount;
194 BOOL bDoSwitch, bForward, bNowSticky;
195 PLSWDATA plswData;
196
197#ifndef XWORKPLACE
198 EXCEPTIONREGISTRATIONRECORD exRegRec;
199
200 LoadExceptq(&exRegRec, "", NULL);
201#endif
202 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, +31, 0);
203
204 plswData = (PLSWDATA) pParm;
205 InitTaskArr(plswData, TRUE, FALSE, TRUE);
206
207 if (DosQueryEventSem(plswData->hevShift, &ulPostCount), ulPostCount > 0)
208 plswData->usCurrItem = plswData->usItems - 1;
209 else
210 plswData->usCurrItem = 1;
211
212 usPopOpt = 1;
213 VioPopUp(&usPopOpt, 0);
214
215 /* wait until monitor dispatcher registeres a monitor for the popup session and
216 resets the semaphore */
217 usCounter = 0;
218 while (DosQueryEventSem(plswData->hevPopup, &ulPostCount),
219 ulPostCount != 0) {
220 DosSleep(5);
221 usCounter++;
222 if (usCounter > 200) {
223 VioEndPopUp(0);
224#ifndef XWORKPLACE
225 UninstallExceptq(&exRegRec);
226#endif
227 return;
228 }
229 }
230
231 FSPopupMenu(plswData, 0);
232
233 bDoSwitch = FALSE;
234 bNowSticky = FALSE;
235
236 for (;;) {
237 usCount = sizeof(keybuf);
238 if (DosMonRead
239 ((PBYTE) & monInBuf, DCWW_WAIT, (PBYTE) & keybuf, &usCount))
240 break;
241 DosMonWrite((PBYTE) & monOutBuf, (PBYTE) & keybuf, usCount);
242// printf("%x %x %x\n",keybuf.cp.fbStatus,keybuf.cp.fsState,keybuf.mnflags>>8);
243
244 ucScan = keybuf.mnflags >> 8;
245 if (ucScan == (SCAN_TAB | 0x80) || ucScan == SCAN_UP
246 || ucScan == SCAN_DOWN) {
247 bForward = ((ucScan == (SCAN_TAB | 0x80) && !(keybuf.cp.fsState & 3)) || /*check shift status */
248 ucScan == SCAN_DOWN);
249 if (bForward) {
250 if (plswData->usCurrItem < plswData->usItems - 1)
251 plswData->usCurrItem++;
252 else
253 plswData->usCurrItem = 0;
254 }
255 else {
256 if (plswData->usCurrItem > 0)
257 plswData->usCurrItem--;
258 else
259 plswData->usCurrItem = plswData->usItems - 1;
260 }
261
262 if (!plswData->Settings.bScrollItems
263 && plswData->usItems > MAXTEXTITEMS
264 && plswData->usCurrItem == ItemNumFromLineNum(plswData,
265 bForward ?
266 MAXTEXTITEMS :
267 -1)) {
268
269 plswData->iShift +=
270 (SHORT) (bForward ? MAXTEXTITEMS : -MAXTEXTITEMS) / 3;
271 plswData->iShift -=
272 plswData->iShift / max((SHORT) plswData->usItems,
273 1) * plswData->usItems;
274
275 FSPopupMenu(plswData, 0);
276 }
277 else
278 FSPopupMenu(plswData, bForward ? 1 : -1);
279 }
280 else if (ucScan == (((plswData->Settings.bStickyPopup || bNowSticky) ? SCAN_ENTER : plswData->Settings.ucPopupHotKey == 0 ? SCAN_ALT : plswData->Settings.ucPopupHotKey == 1 ? SCAN_CTRL : SCAN_WINLEFT) | 0x80)) { /*Enter, Ctrl or Alt or LeftWin release */
281 bDoSwitch = TRUE;
282 break;
283 }
284 else if (ucScan == (SCAN_SPACE | 0x80) || /* space bar release */
285 ((plswData->Settings.bStickyPopup || bNowSticky)
286 && ucScan == SCAN_ESC))
287 break;
288 else if ((plswData->Settings.ucPopupHotKey == 0
289 && ucScan == (SCAN_CTRL | 0x80))
290 || (plswData->Settings.ucPopupHotKey == 1
291 && ucScan == (SCAN_ALT | 0x80))
292 || (plswData->Settings.ucPopupHotKey == 2
293 && (ucScan == (SCAN_CTRL | 0x80)
294 || ucScan == (SCAN_ALT | 0x80))))
295 bNowSticky = TRUE;
296 }
297 VioEndPopUp(0);
298
299 if (bDoSwitch)
300 WinPostMsg(plswData->hwndPopup, WM_COMMAND,
301 MPFROMSHORT(CMD_SWITCHFROMFS), MPFROM2SHORT(CMDSRC_OTHER,
302 FALSE));
303#ifndef XWORKPLACE
304 UninstallExceptq(&exRegRec);
305#endif
306}
307
308/* this function displays fullscreen popup menu.
309 cmd==0: initialize menu, cmd==1 move cursor to the next item, cmd==-1 to the
310 previous item */
311void FSPopupMenu(LSWDATA * plswData, SHORT cmd)
312{
313 static UCHAR ucAttr, ucLineBuf[TEXTSCRWID + 1], ucTitle[NAMELEN],
314 ucCell[2] =
315 { 32, MENUATTR }, ucMenuHgt, ucLineLen, ucMenuXLeft, ucMenuXRight,
316 ucMenuYTop, ucMenuYBottom;
317 USHORT k, usItem;
318 SHORT iLinesAboveSel;
319 VIOCURSORINFO CursorInfo = { 0 };
320
321 if (cmd == 0) {
322 CursorInfo.attr = -1;
323 VioSetCurType(&CursorInfo, 0);
324 }
325
326 if (plswData->Settings.bOldPopup) {
327 if (cmd != 0) {
328 memset(ucLineBuf, 0, sizeof(ucLineBuf));
329 GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,
330 ucLineBuf, sizeof(ucLineBuf), TRUE);
331 ucLineBuf[TEXTSCRWID - 1] = 0;
332 k = 0;
333 while (ucLineBuf[k])
334 k++;
335 memmove(&ucLineBuf[(TEXTSCRWID - k) >> 1], ucLineBuf, k);
336 memset(ucLineBuf, 0, (TEXTSCRWID - k) >> 1);
337 ucAttr = MENUATTR;
338 VioWrtCharStrAtt(ucLineBuf, TEXTSCRWID, 0, 0, &ucAttr, 0);
339 }
340 return;
341 }
342
343 iLinesAboveSel =
344 (min(MAXTEXTITEMS, plswData->usItems) - 1) / 2 - plswData->iShift +
345 (plswData->Settings.bScrollItems ? 0 : plswData->usCurrItem);
346
347 while (iLinesAboveSel > min(MAXTEXTITEMS, plswData->usItems) - 1
348 || iLinesAboveSel < 0)
349 iLinesAboveSel -= (iLinesAboveSel < 0 ? -1 : 1) * plswData->usItems;
350
351 if (cmd == 0) {
352 ucLineLen = 0;
353 for (k = 0; k < plswData->usItems; k++) {
354 GetItemTitle(plswData->TaskArr[k].hsw, ucTitle, sizeof(ucTitle),
355 TRUE);
356 if (strlen(ucTitle) > ucLineLen)
357 ucLineLen = strlen(ucTitle);
358 }
359 ucLineLen += 2;
360 ucMenuHgt = min(MAXTEXTITEMS, plswData->usItems) + 2;
361 ucMenuXLeft = TEXTSCRWID / 2 - ucLineLen / 2;
362 ucMenuYTop = TEXTSCRHGT / 2 - ucMenuHgt / 2;
363 ucMenuXRight = ucMenuXLeft + ucLineLen;
364 ucMenuYBottom = ucMenuYTop + ucMenuHgt;
365
366 for (k = 0; k < ucMenuHgt; k++) {
367 if (k == 0) {
368 memset(ucLineBuf, 205, ucLineLen);
369 ucLineBuf[0] = 201;
370 ucLineBuf[ucLineLen - 1] = 187;
371 }
372 else if (k == ucMenuHgt - 1) {
373 memset(ucLineBuf, 205, ucLineLen);
374 ucLineBuf[0] = 200;
375 ucLineBuf[ucLineLen - 1] = 188;
376 }
377 else {
378 usItem = ItemNumFromLineNum(plswData, k - 1); //-1 takes care of the frame
379 GetItemTitle(plswData->TaskArr[usItem].hsw, ucTitle,
380 sizeof(ucTitle), TRUE);
381 sprintf(ucLineBuf, "%c%-*s%c", 186, ucLineLen - 2, ucTitle,
382 186);
383 }
384 ucAttr = MENUATTR;
385 VioWrtCharStrAtt(ucLineBuf, ucLineLen, ucMenuYTop + k,
386 ucMenuXLeft, &ucAttr, 0);
387 }
388 }
389 else {
390 if (plswData->Settings.bScrollItems) {
391 if (cmd == 1)
392 VioScrollUp(ucMenuYTop + 1, ucMenuXLeft + 1,
393 ucMenuYBottom - 2, ucMenuXRight - 2, 1, ucCell,
394 0);
395 else
396 VioScrollDn(ucMenuYTop + 1, ucMenuXLeft + 1,
397 ucMenuYBottom - 2, ucMenuXRight - 2, 1, ucCell,
398 0);
399
400 usItem =
401 ItemNumFromLineNum(plswData, cmd == 1 ? ucMenuHgt - 3 : 0);
402 GetItemTitle(plswData->TaskArr[usItem].hsw, ucTitle,
403 sizeof(ucTitle), TRUE);
404 sprintf(ucLineBuf, "%c%-*s%c", 186, ucLineLen - 2, ucTitle, 186);
405 ucAttr = MENUATTR;
406 VioWrtCharStrAtt(ucLineBuf, ucLineLen,
407 cmd == 1 ? ucMenuYBottom - 2 : ucMenuYTop + 1,
408 ucMenuXLeft, &ucAttr, 0);
409 VioWrtNAttr(&ucAttr, ucLineLen - 2,
410 ucMenuYTop + iLinesAboveSel + (cmd == 1 ? 0 : 2),
411 ucMenuXLeft + 1, 0);
412 }
413 else {
414 ucAttr = MENUATTR;
415 VioWrtNAttr(&ucAttr, ucLineLen - 2, ucMenuYTop + iLinesAboveSel +
416 (cmd == 1 ? (iLinesAboveSel == 0 ? ucMenuHgt - 2 : 0)
417 : (iLinesAboveSel ==
418 ucMenuHgt - 3 ? 1 - iLinesAboveSel : 2)),
419 ucMenuXLeft + 1, 0);
420 }
421 }
422 ucAttr = CURSORATTR;
423 VioWrtNAttr(&ucAttr, ucLineLen - 2, ucMenuYTop + iLinesAboveSel + 1,
424 ucMenuXLeft + 1, 0);
425}
Note: See TracBrowser for help on using the repository browser.