this repo has no description
at main 5754 lines 117 kB view raw
1/* 2 OSGLUXWN.c 3 4 Copyright (C) 2009 Michael Hanni, Christian Bauer, 5 Stephan Kochen, Paul C. Pratt, and others 6 7 You can redistribute this file and/or modify it under the terms 8 of version 2 of the GNU General Public License as published by 9 the Free Software Foundation. You should have received a copy 10 of the license along with this file; see the file COPYING. 11 12 This file is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 license for more details. 16*/ 17 18/* 19 Operating System GLUe for X WiNdow system 20 21 All operating system dependent code for the 22 X Window System should go here. 23 24 This code is descended from Michael Hanni's X 25 port of vMac, by Philip Cummins. 26 I learned more about how X programs work by 27 looking at other programs such as Basilisk II, 28 the UAE Amiga Emulator, Bochs, QuakeForge, 29 DooM Legacy, and the FLTK. A few snippets 30 from them are used here. 31 32 Drag and Drop support is based on the specification 33 "XDND: Drag-and-Drop Protocol for the X Window System" 34 developed by John Lindal at New Planet Software, and 35 looking at included examples, one by Paul Sheer. 36*/ 37 38#include "OSGCOMUI.h" 39#include "OSGCOMUD.h" 40 41#ifdef WantOSGLUXWN 42 43/* --- some simple utilities --- */ 44 45GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount) 46{ 47 (void) memcpy((char *)destPtr, (char *)srcPtr, byteCount); 48} 49 50/* --- control mode and internationalization --- */ 51 52#define NeedCell2PlainAsciiMap 1 53 54#include "INTLCHAR.h" 55 56 57LOCALVAR char *d_arg = NULL; 58LOCALVAR char *n_arg = NULL; 59 60#if CanGetAppPath 61LOCALVAR char *app_parent = NULL; 62LOCALVAR char *app_name = NULL; 63#endif 64 65LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r) 66{ 67 tMacErr err = mnvm_miscErr; 68 int nx = strlen(x); 69 int ny = strlen(y); 70 { 71 if ((nx > 0) && ('/' == x[nx - 1])) { 72 --nx; 73 } 74 { 75 int nr = nx + 1 + ny; 76 char *p = malloc(nr + 1); 77 if (p != NULL) { 78 char *p2 = p; 79 (void) memcpy(p2, x, nx); 80 p2 += nx; 81 *p2++ = '/'; 82 (void) memcpy(p2, y, ny); 83 p2 += ny; 84 *p2 = 0; 85 *r = p; 86 err = mnvm_noErr; 87 } 88 } 89 } 90 91 return err; 92} 93 94#if UseActvFile || IncludeSonyNew 95LOCALFUNC tMacErr FindOrMakeChild(char *x, char *y, char **r) 96{ 97 tMacErr err; 98 struct stat folder_info; 99 char *r0; 100 101 if (mnvm_noErr == (err = ChildPath(x, y, &r0))) { 102 if (0 != stat(r0, &folder_info)) { 103 if (0 != mkdir(r0, S_IRWXU)) { 104 err = mnvm_miscErr; 105 } else { 106 *r = r0; 107 err = mnvm_noErr; 108 } 109 } else { 110 if (! S_ISDIR(folder_info.st_mode)) { 111 err = mnvm_miscErr; 112 } else { 113 *r = r0; 114 err = mnvm_noErr; 115 } 116 } 117 } 118 119 return err; 120} 121#endif 122 123LOCALPROC MyMayFree(char *p) 124{ 125 if (NULL != p) { 126 free(p); 127 } 128} 129 130/* --- sending debugging info to file --- */ 131 132#if dbglog_HAVE 133 134#ifndef dbglog_ToStdErr 135#define dbglog_ToStdErr 0 136#endif 137 138#if ! dbglog_ToStdErr 139LOCALVAR FILE *dbglog_File = NULL; 140#endif 141 142LOCALFUNC blnr dbglog_open0(void) 143{ 144#if dbglog_ToStdErr 145 return trueblnr; 146#else 147 dbglog_File = fopen("dbglog.txt", "w"); 148 return (NULL != dbglog_File); 149#endif 150} 151 152LOCALPROC dbglog_write0(char *s, uimr L) 153{ 154#if dbglog_ToStdErr 155 (void) fwrite(s, 1, L, stderr); 156#else 157 if (dbglog_File != NULL) { 158 (void) fwrite(s, 1, L, dbglog_File); 159 } 160#endif 161} 162 163LOCALPROC dbglog_close0(void) 164{ 165#if ! dbglog_ToStdErr 166 if (dbglog_File != NULL) { 167 fclose(dbglog_File); 168 dbglog_File = NULL; 169 } 170#endif 171} 172 173#endif 174 175/* --- debug settings and utilities --- */ 176 177#if ! dbglog_HAVE 178#define WriteExtraErr(s) 179#else 180LOCALPROC WriteExtraErr(char *s) 181{ 182 dbglog_writeCStr("*** error: "); 183 dbglog_writeCStr(s); 184 dbglog_writeReturn(); 185} 186#endif 187 188LOCALVAR Display *x_display = NULL; 189 190#define MyDbgEvents (dbglog_HAVE && 0) 191 192#if MyDbgEvents 193LOCALPROC WriteDbgAtom(char *s, Atom x) 194{ 195 char *name = XGetAtomName(x_display, x); 196 if (name != NULL) { 197 dbglog_writeCStr("Atom "); 198 dbglog_writeCStr(s); 199 dbglog_writeCStr(": "); 200 dbglog_writeCStr(name); 201 dbglog_writeReturn(); 202 XFree(name); 203 } 204} 205#endif 206 207/* --- information about the environment --- */ 208 209LOCALVAR Atom MyXA_DeleteW = (Atom)0; 210#if EnableDragDrop 211LOCALVAR Atom MyXA_UriList = (Atom)0; 212LOCALVAR Atom MyXA_DndAware = (Atom)0; 213LOCALVAR Atom MyXA_DndEnter = (Atom)0; 214LOCALVAR Atom MyXA_DndLeave = (Atom)0; 215LOCALVAR Atom MyXA_DndDrop = (Atom)0; 216LOCALVAR Atom MyXA_DndPosition = (Atom)0; 217LOCALVAR Atom MyXA_DndStatus = (Atom)0; 218LOCALVAR Atom MyXA_DndActionCopy = (Atom)0; 219LOCALVAR Atom MyXA_DndActionPrivate = (Atom)0; 220LOCALVAR Atom MyXA_DndSelection = (Atom)0; 221LOCALVAR Atom MyXA_DndFinished = (Atom)0; 222LOCALVAR Atom MyXA_MinivMac_DndXchng = (Atom)0; 223LOCALVAR Atom MyXA_NetActiveWindow = (Atom)0; 224LOCALVAR Atom MyXA_NetSupported = (Atom)0; 225#endif 226#if IncludeHostTextClipExchange 227LOCALVAR Atom MyXA_CLIPBOARD = (Atom)0; 228LOCALVAR Atom MyXA_TARGETS = (Atom)0; 229LOCALVAR Atom MyXA_MinivMac_Clip = (Atom)0; 230#endif 231 232LOCALPROC LoadMyXA(void) 233{ 234 MyXA_DeleteW = XInternAtom(x_display, "WM_DELETE_WINDOW", False); 235#if EnableDragDrop 236 MyXA_UriList = XInternAtom (x_display, "text/uri-list", False); 237 MyXA_DndAware = XInternAtom (x_display, "XdndAware", False); 238 MyXA_DndEnter = XInternAtom(x_display, "XdndEnter", False); 239 MyXA_DndLeave = XInternAtom(x_display, "XdndLeave", False); 240 MyXA_DndDrop = XInternAtom(x_display, "XdndDrop", False); 241 MyXA_DndPosition = XInternAtom(x_display, "XdndPosition", False); 242 MyXA_DndStatus = XInternAtom(x_display, "XdndStatus", False); 243 MyXA_DndActionCopy = XInternAtom(x_display, 244 "XdndActionCopy", False); 245 MyXA_DndActionPrivate = XInternAtom(x_display, 246 "XdndActionPrivate", False); 247 MyXA_DndSelection = XInternAtom(x_display, "XdndSelection", False); 248 MyXA_DndFinished = XInternAtom(x_display, "XdndFinished", False); 249 MyXA_MinivMac_DndXchng = XInternAtom(x_display, 250 "_MinivMac_DndXchng", False); 251 MyXA_NetActiveWindow = XInternAtom(x_display, 252 "_NET_ACTIVE_WINDOW", False); 253 MyXA_NetSupported = XInternAtom(x_display, 254 "_NET_SUPPORTED", False); 255#endif 256#if IncludeHostTextClipExchange 257 MyXA_CLIPBOARD = XInternAtom(x_display, "CLIPBOARD", False); 258 MyXA_TARGETS = XInternAtom(x_display, "TARGETS", False); 259 MyXA_MinivMac_Clip = XInternAtom(x_display, 260 "_MinivMac_Clip", False); 261#endif 262} 263 264#if EnableDragDrop 265LOCALFUNC blnr NetSupportedContains(Atom x) 266{ 267 /* 268 Note that the window manager could be replaced at 269 any time, so don't cache results of this function. 270 */ 271 Atom ret_type; 272 int ret_format; 273 unsigned long ret_item; 274 unsigned long remain_byte; 275 unsigned long i; 276 unsigned char *s = 0; 277 blnr foundit = falseblnr; 278 Window rootwin = XRootWindow(x_display, 279 DefaultScreen(x_display)); 280 281 if (Success != XGetWindowProperty(x_display, rootwin, 282 MyXA_NetSupported, 283 0, 65535, False, XA_ATOM, &ret_type, &ret_format, 284 &ret_item, &remain_byte, &s)) 285 { 286 WriteExtraErr("XGetWindowProperty failed"); 287 } else if (! s) { 288 WriteExtraErr("XGetWindowProperty failed"); 289 } else if (ret_type != XA_ATOM) { 290 WriteExtraErr("XGetWindowProperty returns wrong type"); 291 } else { 292 Atom *v = (Atom *)s; 293 294 for (i = 0; i < ret_item; ++i) { 295 if (v[i] == x) { 296 foundit = trueblnr; 297 /* fprintf(stderr, "found the hint\n"); */ 298 } 299 } 300 } 301 if (s) { 302 XFree(s); 303 } 304 return foundit; 305} 306#endif 307 308#define WantColorTransValid 1 309 310#include "COMOSGLU.h" 311 312#include "PBUFSTDC.h" 313 314#include "CONTROLM.h" 315 316/* --- text translation --- */ 317 318#if IncludePbufs 319/* this is table for Windows, any changes needed for X? */ 320LOCALVAR const ui3b Native2MacRomanTab[] = { 321 0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0, 322 0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7, 323 0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1, 324 0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9, 325 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4, 326 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8, 327 0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1, 328 0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0, 329 0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82, 330 0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC, 331 0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9, 332 0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7, 333 0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D, 334 0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, 335 0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6, 336 0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8 337}; 338#endif 339 340#if IncludePbufs 341LOCALFUNC tMacErr NativeTextToMacRomanPbuf(char *x, tPbuf *r) 342{ 343 if (NULL == x) { 344 return mnvm_miscErr; 345 } else { 346 ui3p p; 347 ui5b L = strlen(x); 348 349 p = (ui3p)malloc(L); 350 if (NULL == p) { 351 return mnvm_miscErr; 352 } else { 353 ui3b *p0 = (ui3b *)x; 354 ui3b *p1 = (ui3b *)p; 355 int i; 356 357 for (i = L; --i >= 0; ) { 358 ui3b v = *p0++; 359 if (v >= 128) { 360 v = Native2MacRomanTab[v - 128]; 361 } else if (10 == v) { 362 v = 13; 363 } 364 *p1++ = v; 365 } 366 367 return PbufNewFromPtr(p, L, r); 368 } 369 } 370} 371#endif 372 373#if IncludePbufs 374/* this is table for Windows, any changes needed for X? */ 375LOCALVAR const ui3b MacRoman2NativeTab[] = { 376 0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1, 377 0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8, 378 0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3, 379 0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC, 380 0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF, 381 0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8, 382 0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F, 383 0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8, 384 0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB, 385 0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C, 386 0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3, 387 0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD, 388 0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1, 389 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4, 390 0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98, 391 0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE 392}; 393#endif 394 395#if IncludePbufs 396LOCALFUNC blnr MacRomanTextToNativePtr(tPbuf i, blnr IsFileName, 397 ui3p *r) 398{ 399 ui3p p; 400 void *Buffer = PbufDat[i]; 401 ui5b L = PbufSize[i]; 402 403 p = (ui3p)malloc(L + 1); 404 if (p != NULL) { 405 ui3b *p0 = (ui3b *)Buffer; 406 ui3b *p1 = (ui3b *)p; 407 int j; 408 409 if (IsFileName) { 410 for (j = L; --j >= 0; ) { 411 ui3b x = *p0++; 412 if (x < 32) { 413 x = '-'; 414 } else if (x >= 128) { 415 x = MacRoman2NativeTab[x - 128]; 416 } else { 417 switch (x) { 418 case '/': 419 case '<': 420 case '>': 421 case '|': 422 case ':': 423 x = '-'; 424 default: 425 break; 426 } 427 } 428 *p1++ = x; 429 } 430 if ('.' == p[0]) { 431 p[0] = '-'; 432 } 433 } else { 434 for (j = L; --j >= 0; ) { 435 ui3b x = *p0++; 436 if (x >= 128) { 437 x = MacRoman2NativeTab[x - 128]; 438 } else if (13 == x) { 439 x = '\n'; 440 } 441 *p1++ = x; 442 } 443 } 444 *p1 = 0; 445 446 *r = p; 447 return trueblnr; 448 } 449 return falseblnr; 450} 451#endif 452 453LOCALPROC NativeStrFromCStr(char *r, char *s) 454{ 455 ui3b ps[ClStrMaxLength]; 456 int i; 457 int L; 458 459 ClStrFromSubstCStr(&L, ps, s); 460 461 for (i = 0; i < L; ++i) { 462 r[i] = Cell2PlainAsciiMap[ps[i]]; 463 } 464 465 r[L] = 0; 466} 467 468/* --- drives --- */ 469 470#define NotAfileRef NULL 471 472LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */ 473#if IncludeSonyGetName || IncludeSonyNew 474LOCALVAR char *DriveNames[NumDrives]; 475#endif 476 477LOCALPROC InitDrives(void) 478{ 479 /* 480 This isn't really needed, Drives[i] and DriveNames[i] 481 need not have valid values when not vSonyIsInserted[i]. 482 */ 483 tDrive i; 484 485 for (i = 0; i < NumDrives; ++i) { 486 Drives[i] = NotAfileRef; 487#if IncludeSonyGetName || IncludeSonyNew 488 DriveNames[i] = NULL; 489#endif 490 } 491} 492 493GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, 494 tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, 495 ui5r *Sony_ActCount) 496{ 497 tMacErr err = mnvm_miscErr; 498 FILE *refnum = Drives[Drive_No]; 499 ui5r NewSony_Count = 0; 500 501 if (0 == fseek(refnum, Sony_Start, SEEK_SET)) { 502 if (IsWrite) { 503 NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum); 504 } else { 505 NewSony_Count = fread(Buffer, 1, Sony_Count, refnum); 506 } 507 508 if (NewSony_Count == Sony_Count) { 509 err = mnvm_noErr; 510 } 511 } 512 513 if (nullpr != Sony_ActCount) { 514 *Sony_ActCount = NewSony_Count; 515 } 516 517 return err; /*& figure out what really to return &*/ 518} 519 520GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count) 521{ 522 tMacErr err = mnvm_miscErr; 523 FILE *refnum = Drives[Drive_No]; 524 long v; 525 526 if (0 == fseek(refnum, 0, SEEK_END)) { 527 v = ftell(refnum); 528 if (v >= 0) { 529 *Sony_Count = v; 530 err = mnvm_noErr; 531 } 532 } 533 534 return err; /*& figure out what really to return &*/ 535} 536 537#ifndef HaveAdvisoryLocks 538#define HaveAdvisoryLocks 1 539#endif 540 541/* 542 What is the difference between fcntl(fd, F_SETLK ... 543 and flock(fd ... ? 544*/ 545 546#if HaveAdvisoryLocks 547LOCALFUNC blnr MyLockFile(FILE *refnum) 548{ 549 blnr IsOk = falseblnr; 550 551#if 1 552 struct flock fl; 553 int fd = fileno(refnum); 554 555 fl.l_start = 0; /* starting offset */ 556 fl.l_len = 0; /* len = 0 means until end of file */ 557 /* fl.pid_t l_pid; */ /* lock owner, don't need to set */ 558 fl.l_type = F_WRLCK; /* lock type: read/write, etc. */ 559 fl.l_whence = SEEK_SET; /* type of l_start */ 560 if (-1 == fcntl(fd, F_SETLK, &fl)) { 561 MacMsg(kStrImageInUseTitle, kStrImageInUseMessage, 562 falseblnr); 563 } else { 564 IsOk = trueblnr; 565 } 566#else 567 int fd = fileno(refnum); 568 569 if (-1 == flock(fd, LOCK_EX | LOCK_NB)) { 570 MacMsg(kStrImageInUseTitle, kStrImageInUseMessage, 571 falseblnr); 572 } else { 573 IsOk = trueblnr; 574 } 575#endif 576 577 return IsOk; 578} 579#endif 580 581#if HaveAdvisoryLocks 582LOCALPROC MyUnlockFile(FILE *refnum) 583{ 584#if 1 585 struct flock fl; 586 int fd = fileno(refnum); 587 588 fl.l_start = 0; /* starting offset */ 589 fl.l_len = 0; /* len = 0 means until end of file */ 590 /* fl.pid_t l_pid; */ /* lock owner, don't need to set */ 591 fl.l_type = F_UNLCK; /* lock type: read/write, etc. */ 592 fl.l_whence = SEEK_SET; /* type of l_start */ 593 if (-1 == fcntl(fd, F_SETLK, &fl)) { 594 /* an error occurred */ 595 } 596#else 597 int fd = fileno(refnum); 598 599 if (-1 == flock(fd, LOCK_UN)) { 600 } 601#endif 602} 603#endif 604 605LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit) 606{ 607 FILE *refnum = Drives[Drive_No]; 608 609 DiskEjectedNotify(Drive_No); 610 611#if HaveAdvisoryLocks 612 MyUnlockFile(refnum); 613#endif 614 615 fclose(refnum); 616 Drives[Drive_No] = NotAfileRef; /* not really needed */ 617 618#if IncludeSonyGetName || IncludeSonyNew 619 { 620 char *s = DriveNames[Drive_No]; 621 if (NULL != s) { 622 if (deleteit) { 623 remove(s); 624 } 625 free(s); 626 DriveNames[Drive_No] = NULL; /* not really needed */ 627 } 628 } 629#endif 630 631 return mnvm_noErr; 632} 633 634GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No) 635{ 636 return vSonyEject0(Drive_No, falseblnr); 637} 638 639#if IncludeSonyNew 640GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No) 641{ 642 return vSonyEject0(Drive_No, trueblnr); 643} 644#endif 645 646LOCALPROC UnInitDrives(void) 647{ 648 tDrive i; 649 650 for (i = 0; i < NumDrives; ++i) { 651 if (vSonyIsInserted(i)) { 652 (void) vSonyEject(i); 653 } 654 } 655} 656 657#if IncludeSonyGetName 658GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r) 659{ 660 char *drivepath = DriveNames[Drive_No]; 661 if (NULL == drivepath) { 662 return mnvm_miscErr; 663 } else { 664 char *s = strrchr(drivepath, '/'); 665 if (NULL == s) { 666 s = drivepath; 667 } else { 668 ++s; 669 } 670 return NativeTextToMacRomanPbuf(s, r); 671 } 672} 673#endif 674 675LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked, 676 char *drivepath) 677{ 678 tDrive Drive_No; 679 blnr IsOk = falseblnr; 680 681 if (! FirstFreeDisk(&Drive_No)) { 682 MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage, 683 falseblnr); 684 } else { 685 /* printf("Sony_Insert0 %d\n", (int)Drive_No); */ 686 687#if HaveAdvisoryLocks 688 if (locked || MyLockFile(refnum)) 689#endif 690 { 691 Drives[Drive_No] = refnum; 692 DiskInsertNotify(Drive_No, locked); 693 694#if IncludeSonyGetName || IncludeSonyNew 695 { 696 ui5b L = strlen(drivepath); 697 char *p = malloc(L + 1); 698 if (p != NULL) { 699 (void) memcpy(p, drivepath, L + 1); 700 } 701 DriveNames[Drive_No] = p; 702 } 703#endif 704 705 IsOk = trueblnr; 706 } 707 } 708 709 if (! IsOk) { 710 fclose(refnum); 711 } 712 713 return IsOk; 714} 715 716LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail) 717{ 718 blnr locked = falseblnr; 719 /* printf("Sony_Insert1 %s\n", drivepath); */ 720 FILE *refnum = fopen(drivepath, "rb+"); 721 if (NULL == refnum) { 722 locked = trueblnr; 723 refnum = fopen(drivepath, "rb"); 724 } 725 if (NULL == refnum) { 726 if (! silentfail) { 727 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); 728 } 729 } else { 730 return Sony_Insert0(refnum, locked, drivepath); 731 } 732 return falseblnr; 733} 734 735LOCALFUNC tMacErr LoadMacRomFrom(char *path) 736{ 737 tMacErr err; 738 FILE *ROM_File; 739 int File_Size; 740 741 ROM_File = fopen(path, "rb"); 742 if (NULL == ROM_File) { 743 err = mnvm_fnfErr; 744 } else { 745 File_Size = fread(ROM, 1, kROM_Size, ROM_File); 746 if (kROM_Size != File_Size) { 747 if (feof(ROM_File)) { 748 MacMsgOverride(kStrShortROMTitle, 749 kStrShortROMMessage); 750 err = mnvm_eofErr; 751 } else { 752 MacMsgOverride(kStrNoReadROMTitle, 753 kStrNoReadROMMessage); 754 err = mnvm_miscErr; 755 } 756 } else { 757 err = ROM_IsValid(); 758 } 759 fclose(ROM_File); 760 } 761 762 return err; 763} 764 765LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail) 766{ 767 blnr v; 768 769 if (! ROM_loaded) { 770 v = (mnvm_noErr == LoadMacRomFrom(drivepath)); 771 } else { 772 v = Sony_Insert1(drivepath, silentfail); 773 } 774 775 return v; 776} 777 778LOCALFUNC blnr Sony_Insert2(char *s) 779{ 780 char *d = 781#if CanGetAppPath 782 (NULL == d_arg) ? app_parent : 783#endif 784 d_arg; 785 blnr IsOk = falseblnr; 786 787 if (NULL == d) { 788 IsOk = Sony_Insert1(s, trueblnr); 789 } else { 790 char *t; 791 792 if (mnvm_noErr == ChildPath(d, s, &t)) { 793 IsOk = Sony_Insert1(t, trueblnr); 794 free(t); 795 } 796 } 797 798 return IsOk; 799} 800 801LOCALFUNC blnr Sony_InsertIth(int i) 802{ 803 blnr v; 804 805 if ((i > 9) || ! FirstFreeDisk(nullpr)) { 806 v = falseblnr; 807 } else { 808 char s[] = "disk?.dsk"; 809 810 s[4] = '0' + i; 811 812 v = Sony_Insert2(s); 813 } 814 815 return v; 816} 817 818LOCALFUNC blnr LoadInitialImages(void) 819{ 820 if (! AnyDiskInserted()) { 821 int i; 822 823 for (i = 1; Sony_InsertIth(i); ++i) { 824 /* stop on first error (including file not found) */ 825 } 826 } 827 828 return trueblnr; 829} 830 831#if IncludeSonyNew 832LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L) 833{ 834#define ZeroBufferSize 2048 835 ui5b i; 836 ui3b buffer[ZeroBufferSize]; 837 838 memset(&buffer, 0, ZeroBufferSize); 839 840 while (L > 0) { 841 i = (L > ZeroBufferSize) ? ZeroBufferSize : L; 842 if (fwrite(buffer, 1, i, refnum) != i) { 843 return falseblnr; 844 } 845 L -= i; 846 } 847 return trueblnr; 848} 849#endif 850 851#if IncludeSonyNew 852LOCALPROC MakeNewDisk0(ui5b L, char *drivepath) 853{ 854 blnr IsOk = falseblnr; 855 FILE *refnum = fopen(drivepath, "wb+"); 856 if (NULL == refnum) { 857 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); 858 } else { 859 if (WriteZero(refnum, L)) { 860 IsOk = Sony_Insert0(refnum, falseblnr, drivepath); 861 refnum = NULL; 862 } 863 if (refnum != NULL) { 864 fclose(refnum); 865 } 866 if (! IsOk) { 867 (void) remove(drivepath); 868 } 869 } 870} 871#endif 872 873#if IncludeSonyNew 874LOCALPROC MakeNewDisk(ui5b L, char *drivename) 875{ 876 char *d = 877#if CanGetAppPath 878 (NULL == d_arg) ? app_parent : 879#endif 880 d_arg; 881 882 if (NULL == d) { 883 MakeNewDisk0(L, drivename); /* in current directory */ 884 } else { 885 tMacErr err; 886 char *t = NULL; 887 char *t2 = NULL; 888 889 if (mnvm_noErr == (err = FindOrMakeChild(d, "out", &t))) 890 if (mnvm_noErr == (err = ChildPath(t, drivename, &t2))) 891 { 892 MakeNewDisk0(L, t2); 893 } 894 895 MyMayFree(t2); 896 MyMayFree(t); 897 } 898} 899#endif 900 901#if IncludeSonyNew 902LOCALPROC MakeNewDiskAtDefault(ui5b L) 903{ 904 char s[ClStrMaxLength + 1]; 905 906 NativeStrFromCStr(s, "untitled.dsk"); 907 MakeNewDisk(L, s); 908} 909#endif 910 911/* --- ROM --- */ 912 913LOCALVAR char *rom_path = NULL; 914 915#if 0 916#include <pwd.h> 917#include <unistd.h> 918#endif 919 920LOCALFUNC tMacErr FindUserHomeFolder(char **r) 921{ 922 tMacErr err; 923 char *s; 924#if 0 925 struct passwd *user; 926#endif 927 928 if (NULL != (s = getenv("HOME"))) { 929 *r = s; 930 err = mnvm_noErr; 931 } else 932#if 0 933 if ((NULL != (user = getpwuid(getuid()))) 934 && (NULL != (s = user->pw_dir))) 935 { 936 /* 937 From getpwuid man page: 938 "An application that wants to determine its user's 939 home directory should inspect the value of HOME 940 (rather than the value getpwuid(getuid())->pw_dir) 941 since this allows the user to modify their notion of 942 "the home directory" during a login session." 943 944 But it is possible for HOME to not be set. 945 Some sources say to use getpwuid in that case. 946 */ 947 *r = s; 948 err = mnvm_noErr; 949 } else 950#endif 951 { 952 err = mnvm_fnfErr; 953 } 954 955 return err; 956} 957 958LOCALFUNC tMacErr LoadMacRomFromHome(void) 959{ 960 tMacErr err; 961 char *s; 962 char *t = NULL; 963 char *t2 = NULL; 964 char *t3 = NULL; 965 966 if (mnvm_noErr == (err = FindUserHomeFolder(&s))) 967 if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t))) 968 if (mnvm_noErr == (err = ChildPath(t, "mnvm_rom", &t2))) 969 if (mnvm_noErr == (err = ChildPath(t2, RomFileName, &t3))) 970 { 971 err = LoadMacRomFrom(t3); 972 } 973 974 MyMayFree(t3); 975 MyMayFree(t2); 976 MyMayFree(t); 977 978 return err; 979} 980 981#if CanGetAppPath 982LOCALFUNC tMacErr LoadMacRomFromAppPar(void) 983{ 984 tMacErr err; 985 char *d = 986#if CanGetAppPath 987 (NULL == d_arg) ? app_parent : 988#endif 989 d_arg; 990 char *t = NULL; 991 992 if (NULL == d) { 993 err = mnvm_fnfErr; 994 } else { 995 if (mnvm_noErr == (err = ChildPath(d, RomFileName, 996 &t))) 997 { 998 err = LoadMacRomFrom(t); 999 } 1000 } 1001 1002 MyMayFree(t); 1003 1004 return err; 1005} 1006#endif 1007 1008LOCALFUNC blnr LoadMacRom(void) 1009{ 1010 tMacErr err; 1011 1012 if ((NULL == rom_path) 1013 || (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path)))) 1014#if CanGetAppPath 1015 if (mnvm_fnfErr == (err = LoadMacRomFromAppPar())) 1016#endif 1017 if (mnvm_fnfErr == (err = LoadMacRomFromHome())) 1018 if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName))) 1019 { 1020 } 1021 1022 return trueblnr; /* keep launching Mini vMac, regardless */ 1023} 1024 1025#if UseActvFile 1026 1027#define ActvCodeFileName "act_1" 1028 1029LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p) 1030{ 1031 tMacErr err; 1032 char *s; 1033 char *t = NULL; 1034 char *t2 = NULL; 1035 char *t3 = NULL; 1036 1037 if (mnvm_noErr == (err = FindUserHomeFolder(&s))) 1038 if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t))) 1039 if (mnvm_noErr == (err = ChildPath(t, "mnvm_act", &t2))) 1040 if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3))) 1041 { 1042 FILE *Actv_File; 1043 int File_Size; 1044 1045 Actv_File = fopen(t3, "rb"); 1046 if (NULL == Actv_File) { 1047 err = mnvm_fnfErr; 1048 } else { 1049 File_Size = fread(p, 1, ActvCodeFileLen, Actv_File); 1050 if (File_Size != ActvCodeFileLen) { 1051 if (feof(Actv_File)) { 1052 err = mnvm_eofErr; 1053 } else { 1054 err = mnvm_miscErr; 1055 } 1056 } else { 1057 err = mnvm_noErr; 1058 } 1059 fclose(Actv_File); 1060 } 1061 } 1062 1063 MyMayFree(t3); 1064 MyMayFree(t2); 1065 MyMayFree(t); 1066 1067 return err; 1068} 1069 1070LOCALFUNC tMacErr ActvCodeFileSave(ui3p p) 1071{ 1072 tMacErr err; 1073 char *s; 1074 char *t = NULL; 1075 char *t2 = NULL; 1076 char *t3 = NULL; 1077 1078 if (mnvm_noErr == (err = FindUserHomeFolder(&s))) 1079 if (mnvm_noErr == (err = FindOrMakeChild(s, ".gryphel", &t))) 1080 if (mnvm_noErr == (err = FindOrMakeChild(t, "mnvm_act", &t2))) 1081 if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3))) 1082 { 1083 FILE *Actv_File; 1084 int File_Size; 1085 1086 Actv_File = fopen(t3, "wb+"); 1087 if (NULL == Actv_File) { 1088 err = mnvm_fnfErr; 1089 } else { 1090 File_Size = fwrite(p, 1, ActvCodeFileLen, Actv_File); 1091 if (File_Size != ActvCodeFileLen) { 1092 err = mnvm_miscErr; 1093 } else { 1094 err = mnvm_noErr; 1095 } 1096 fclose(Actv_File); 1097 } 1098 } 1099 1100 MyMayFree(t3); 1101 MyMayFree(t2); 1102 MyMayFree(t); 1103 1104 return err; 1105} 1106 1107#endif /* UseActvFile */ 1108 1109/* --- video out --- */ 1110 1111LOCALVAR Window my_main_wind = 0; 1112LOCALVAR GC my_gc = NULL; 1113LOCALVAR blnr NeedFinishOpen1 = falseblnr; 1114LOCALVAR blnr NeedFinishOpen2 = falseblnr; 1115 1116LOCALVAR XColor x_black; 1117LOCALVAR XColor x_white; 1118 1119#if MayFullScreen 1120LOCALVAR short hOffset; 1121LOCALVAR short vOffset; 1122#endif 1123 1124#if VarFullScreen 1125LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0); 1126#endif 1127 1128#if EnableMagnify 1129LOCALVAR blnr UseMagnify = (WantInitMagnify != 0); 1130#endif 1131 1132LOCALVAR blnr gBackgroundFlag = falseblnr; 1133LOCALVAR blnr gTrueBackgroundFlag = falseblnr; 1134LOCALVAR blnr CurSpeedStopped = trueblnr; 1135 1136#ifndef UseColorImage 1137#define UseColorImage (0 != vMacScreenDepth) 1138#endif 1139 1140LOCALVAR XImage *my_image = NULL; 1141 1142#if EnableMagnify 1143LOCALVAR XImage *my_Scaled_image = NULL; 1144#endif 1145 1146#if EnableMagnify 1147#define MaxScale MyWindowScale 1148#else 1149#define MaxScale 1 1150#endif 1151 1152#define WantScalingTabl (EnableMagnify || UseColorImage) 1153 1154#if WantScalingTabl 1155 1156LOCALVAR ui3p ScalingTabl = nullpr; 1157 1158#define ScalingTablsz1 (256 * MaxScale) 1159 1160#if UseColorImage 1161#define ScalingTablsz (ScalingTablsz1 << 5) 1162#else 1163#define ScalingTablsz ScalingTablsz1 1164#endif 1165 1166#endif /* WantScalingTabl */ 1167 1168 1169#define WantScalingBuff (EnableMagnify || UseColorImage) 1170 1171#if WantScalingBuff 1172 1173LOCALVAR ui3p ScalingBuff = nullpr; 1174 1175 1176#if UseColorImage 1177#define ScalingBuffsz \ 1178 (vMacScreenNumPixels * 4 * MaxScale * MaxScale) 1179#else 1180#define ScalingBuffsz ((long)vMacScreenMonoNumBytes \ 1181 * MaxScale * MaxScale) 1182#endif 1183 1184#endif /* WantScalingBuff */ 1185 1186 1187#if EnableMagnify && ! UseColorImage 1188LOCALPROC SetUpScalingTabl(void) 1189{ 1190 ui3b *p4; 1191 int i; 1192 int j; 1193 int k; 1194 ui3r bitsRemaining; 1195 ui3b t1; 1196 ui3b t2; 1197 1198 p4 = ScalingTabl; 1199 for (i = 0; i < 256; ++i) { 1200 bitsRemaining = 8; 1201 t2 = 0; 1202 for (j = 8; --j >= 0; ) { 1203 t1 = (i >> j) & 1; 1204 for (k = MyWindowScale; --k >= 0; ) { 1205 t2 = (t2 << 1) | t1; 1206 if (--bitsRemaining == 0) { 1207 *p4++ = t2; 1208 bitsRemaining = 8; 1209 t2 = 0; 1210 } 1211 } 1212 } 1213 } 1214} 1215#endif 1216 1217#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4) 1218LOCALPROC SetUpColorScalingTabl(void) 1219{ 1220 int i; 1221 int j; 1222 int k; 1223 int a; 1224 ui5r v; 1225 ui5p p4; 1226 1227 p4 = (ui5p)ScalingTabl; 1228 for (i = 0; i < 256; ++i) { 1229 for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) { 1230 j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1); 1231 v = (((long)CLUT_reds[j] & 0xFF00) << 8) 1232 | ((long)CLUT_greens[j] & 0xFF00) 1233 | (((long)CLUT_blues[j] & 0xFF00) >> 8); 1234 for (a = MyWindowScale; --a >= 0; ) { 1235 *p4++ = v; 1236 } 1237 } 1238 } 1239} 1240#endif 1241 1242#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) 1243LOCALPROC SetUpColorTabl(void) 1244{ 1245 int i; 1246 int j; 1247 int k; 1248 ui5p p4; 1249 1250 p4 = (ui5p)ScalingTabl; 1251 for (i = 0; i < 256; ++i) { 1252 for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) { 1253 j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1); 1254 *p4++ = (((long)CLUT_reds[j] & 0xFF00) << 8) 1255 | ((long)CLUT_greens[j] & 0xFF00) 1256 | (((long)CLUT_blues[j] & 0xFF00) >> 8); 1257 } 1258 } 1259} 1260#endif 1261 1262#if EnableMagnify && UseColorImage 1263LOCALPROC SetUpBW2ColorScalingTabl(void) 1264{ 1265 int i; 1266 int k; 1267 int a; 1268 ui5r v; 1269 ui5p p4; 1270 1271 p4 = (ui5p)ScalingTabl; 1272 for (i = 0; i < 256; ++i) { 1273 for (k = 8; --k >= 0; ) { 1274 if (0 != ((i >> k) & 1)) { 1275 v = 0; 1276 } else { 1277 v = 0xFFFFFF; 1278 } 1279 1280 for (a = MyWindowScale; --a >= 0; ) { 1281 *p4++ = v; 1282 } 1283 } 1284 } 1285} 1286#endif 1287 1288#if UseColorImage 1289LOCALPROC SetUpBW2ColorTabl(void) 1290{ 1291 int i; 1292 int k; 1293 ui5r v; 1294 ui5p p4; 1295 1296 p4 = (ui5p)ScalingTabl; 1297 for (i = 0; i < 256; ++i) { 1298 for (k = 8; --k >= 0; ) { 1299 if (0 != ((i >> k) & 1)) { 1300 v = 0; 1301 } else { 1302 v = 0xFFFFFF; 1303 } 1304 *p4++ = v; 1305 } 1306 } 1307} 1308#endif 1309 1310 1311#if EnableMagnify && ! UseColorImage 1312 1313#define ScrnMapr_DoMap UpdateScaledBWCopy 1314#define ScrnMapr_Src GetCurDrawBuff() 1315#define ScrnMapr_Dst ScalingBuff 1316#define ScrnMapr_SrcDepth 0 1317#define ScrnMapr_DstDepth 0 1318#define ScrnMapr_Map ScalingTabl 1319#define ScrnMapr_Scale MyWindowScale 1320 1321#include "SCRNMAPR.h" 1322 1323#endif 1324 1325 1326#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) 1327 1328#define ScrnMapr_DoMap UpdateMappedColorCopy 1329#define ScrnMapr_Src GetCurDrawBuff() 1330#define ScrnMapr_Dst ScalingBuff 1331#define ScrnMapr_SrcDepth vMacScreenDepth 1332#define ScrnMapr_DstDepth 5 1333#define ScrnMapr_Map ScalingTabl 1334 1335#include "SCRNMAPR.h" 1336 1337#endif 1338 1339 1340#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4) 1341 1342#define ScrnMapr_DoMap UpdateMappedScaledColorCopy 1343#define ScrnMapr_Src GetCurDrawBuff() 1344#define ScrnMapr_Dst ScalingBuff 1345#define ScrnMapr_SrcDepth vMacScreenDepth 1346#define ScrnMapr_DstDepth 5 1347#define ScrnMapr_Map ScalingTabl 1348#define ScrnMapr_Scale MyWindowScale 1349 1350#include "SCRNMAPR.h" 1351 1352#endif 1353 1354 1355#if vMacScreenDepth >= 4 1356 1357#define ScrnTrns_DoTrans UpdateTransColorCopy 1358#define ScrnTrns_Src GetCurDrawBuff() 1359#define ScrnTrns_Dst ScalingBuff 1360#define ScrnTrns_SrcDepth vMacScreenDepth 1361#define ScrnTrns_DstDepth 5 1362 1363#include "SCRNTRNS.h" 1364 1365#endif 1366 1367#if EnableMagnify && (vMacScreenDepth >= 4) 1368 1369#define ScrnTrns_DoTrans UpdateTransScaledColorCopy 1370#define ScrnTrns_Src GetCurDrawBuff() 1371#define ScrnTrns_Dst ScalingBuff 1372#define ScrnTrns_SrcDepth vMacScreenDepth 1373#define ScrnTrns_DstDepth 5 1374#define ScrnTrns_Scale MyWindowScale 1375 1376#include "SCRNTRNS.h" 1377 1378#endif 1379 1380 1381#if EnableMagnify && UseColorImage 1382 1383#define ScrnMapr_DoMap UpdateMappedScaledBW2ColorCopy 1384#define ScrnMapr_Src GetCurDrawBuff() 1385#define ScrnMapr_Dst ScalingBuff 1386#define ScrnMapr_SrcDepth 0 1387#define ScrnMapr_DstDepth 5 1388#define ScrnMapr_Map ScalingTabl 1389#define ScrnMapr_Scale MyWindowScale 1390 1391#include "SCRNMAPR.h" 1392 1393#endif 1394 1395 1396#if UseColorImage 1397 1398#define ScrnMapr_DoMap UpdateMappedBW2ColorCopy 1399#define ScrnMapr_Src GetCurDrawBuff() 1400#define ScrnMapr_Dst ScalingBuff 1401#define ScrnMapr_SrcDepth 0 1402#define ScrnMapr_DstDepth 5 1403#define ScrnMapr_Map ScalingTabl 1404 1405#include "SCRNMAPR.h" 1406 1407#endif 1408 1409 1410LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left, 1411 ui4r bottom, ui4r right) 1412{ 1413 int XDest; 1414 int YDest; 1415 char *the_data; 1416 1417#if VarFullScreen 1418 if (UseFullScreen) 1419#endif 1420#if MayFullScreen 1421 { 1422 if (top < ViewVStart) { 1423 top = ViewVStart; 1424 } 1425 if (left < ViewHStart) { 1426 left = ViewHStart; 1427 } 1428 if (bottom > ViewVStart + ViewVSize) { 1429 bottom = ViewVStart + ViewVSize; 1430 } 1431 if (right > ViewHStart + ViewHSize) { 1432 right = ViewHStart + ViewHSize; 1433 } 1434 1435 if ((top >= bottom) || (left >= right)) { 1436 goto label_exit; 1437 } 1438 } 1439#endif 1440 1441 XDest = left; 1442 YDest = top; 1443 1444#if VarFullScreen 1445 if (UseFullScreen) 1446#endif 1447#if MayFullScreen 1448 { 1449 XDest -= ViewHStart; 1450 YDest -= ViewVStart; 1451 } 1452#endif 1453 1454#if EnableMagnify 1455 if (UseMagnify) { 1456 XDest *= MyWindowScale; 1457 YDest *= MyWindowScale; 1458 } 1459#endif 1460 1461#if VarFullScreen 1462 if (UseFullScreen) 1463#endif 1464#if MayFullScreen 1465 { 1466 XDest += hOffset; 1467 YDest += vOffset; 1468 } 1469#endif 1470 1471#if EnableMagnify 1472 if (UseMagnify) { 1473#if UseColorImage 1474#if 0 != vMacScreenDepth 1475 if (UseColorMode) { 1476#if vMacScreenDepth < 4 1477 if (! ColorTransValid) { 1478 SetUpColorScalingTabl(); 1479 ColorTransValid = trueblnr; 1480 } 1481 1482 UpdateMappedScaledColorCopy(top, left, bottom, right); 1483#else 1484 UpdateTransScaledColorCopy(top, left, bottom, right); 1485#endif 1486 } else 1487#endif /* 0 != vMacScreenDepth */ 1488 { 1489 if (! ColorTransValid) { 1490 SetUpBW2ColorScalingTabl(); 1491 ColorTransValid = trueblnr; 1492 } 1493 1494 UpdateMappedScaledBW2ColorCopy(top, left, bottom, right); 1495 } 1496#else /* ! UseColorImage */ 1497 /* assume 0 == vMacScreenDepth */ 1498 { 1499 if (! ColorTransValid) { 1500 SetUpScalingTabl(); 1501 ColorTransValid = trueblnr; 1502 } 1503 1504 UpdateScaledBWCopy(top, left, bottom, right); 1505 } 1506#endif /* UseColorImage */ 1507 1508 { 1509 char *saveData = my_Scaled_image->data; 1510 my_Scaled_image->data = (char *)ScalingBuff; 1511 1512 XPutImage(x_display, my_main_wind, my_gc, my_Scaled_image, 1513 left * MyWindowScale, top * MyWindowScale, 1514 XDest, YDest, 1515 (right - left) * MyWindowScale, 1516 (bottom - top) * MyWindowScale); 1517 1518 my_Scaled_image->data = saveData; 1519 } 1520 } else 1521#endif /* EnableMagnify */ 1522 { 1523#if UseColorImage 1524#if 0 != vMacScreenDepth 1525 if (UseColorMode) { 1526#if vMacScreenDepth < 4 1527 1528 if (! ColorTransValid) { 1529 SetUpColorTabl(); 1530 ColorTransValid = trueblnr; 1531 } 1532 1533 UpdateMappedColorCopy(top, left, bottom, right); 1534 1535 the_data = (char *)ScalingBuff; 1536#else 1537 /* 1538 if vMacScreenDepth == 5 and MSBFirst, could 1539 copy directly with the_data = (char *)GetCurDrawBuff(); 1540 */ 1541 UpdateTransColorCopy(top, left, bottom, right); 1542 1543 the_data = (char *)ScalingBuff; 1544#endif 1545 } else 1546#endif /* 0 != vMacScreenDepth */ 1547 { 1548 if (! ColorTransValid) { 1549 SetUpBW2ColorTabl(); 1550 ColorTransValid = trueblnr; 1551 } 1552 1553 UpdateMappedBW2ColorCopy(top, left, bottom, right); 1554 1555 the_data = (char *)ScalingBuff; 1556 } 1557#else /* ! UseColorImage */ 1558 { 1559 the_data = (char *)GetCurDrawBuff(); 1560 } 1561#endif /* UseColorImage */ 1562 1563 { 1564 char *saveData = my_image->data; 1565 my_image->data = the_data; 1566 1567 XPutImage(x_display, my_main_wind, my_gc, my_image, 1568 left, top, XDest, YDest, 1569 right - left, bottom - top); 1570 1571 my_image->data = saveData; 1572 } 1573 } 1574 1575#if MayFullScreen 1576label_exit: 1577 ; 1578#endif 1579} 1580 1581LOCALPROC MyDrawChangesAndClear(void) 1582{ 1583 if (ScreenChangedBottom > ScreenChangedTop) { 1584 HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft, 1585 ScreenChangedBottom, ScreenChangedRight); 1586 ScreenClearChanges(); 1587 } 1588} 1589 1590/* --- mouse --- */ 1591 1592/* cursor hiding */ 1593 1594LOCALVAR blnr HaveCursorHidden = falseblnr; 1595LOCALVAR blnr WantCursorHidden = falseblnr; 1596 1597LOCALPROC ForceShowCursor(void) 1598{ 1599 if (HaveCursorHidden) { 1600 HaveCursorHidden = falseblnr; 1601 if (my_main_wind) { 1602 XUndefineCursor(x_display, my_main_wind); 1603 } 1604 } 1605} 1606 1607LOCALVAR Cursor blankCursor = None; 1608 1609LOCALFUNC blnr CreateMyBlankCursor(Window rootwin) 1610/* 1611 adapted from X11_CreateNullCursor in context.x11.c 1612 in quakeforge 0.5.5, copyright Id Software, Inc. 1613 Zephaniah E. Hull, and Jeff Teunissen. 1614*/ 1615{ 1616 Pixmap cursormask; 1617 XGCValues xgc; 1618 GC gc; 1619 blnr IsOk = falseblnr; 1620 1621 cursormask = XCreatePixmap(x_display, rootwin, 1, 1, 1); 1622 if (None == cursormask) { 1623 WriteExtraErr("XCreatePixmap failed."); 1624 } else { 1625 xgc.function = GXclear; 1626 gc = XCreateGC(x_display, cursormask, GCFunction, &xgc); 1627 if (None == gc) { 1628 WriteExtraErr("XCreateGC failed."); 1629 } else { 1630 XFillRectangle(x_display, cursormask, gc, 0, 0, 1, 1); 1631 XFreeGC(x_display, gc); 1632 1633 blankCursor = XCreatePixmapCursor(x_display, cursormask, 1634 cursormask, &x_black, &x_white, 0, 0); 1635 if (None == blankCursor) { 1636 WriteExtraErr("XCreatePixmapCursor failed."); 1637 } else { 1638 IsOk = trueblnr; 1639 } 1640 } 1641 1642 XFreePixmap(x_display, cursormask); 1643 /* 1644 assuming that XCreatePixmapCursor doesn't think it 1645 owns the pixmaps passed to it. I've seen code that 1646 assumes this, and other code that seems to assume 1647 the opposite. 1648 */ 1649 } 1650 return IsOk; 1651} 1652 1653/* cursor moving */ 1654 1655#if EnableMoveMouse 1656LOCALFUNC blnr MyMoveMouse(si4b h, si4b v) 1657{ 1658 int NewMousePosh; 1659 int NewMousePosv; 1660 int root_x_return; 1661 int root_y_return; 1662 Window root_return; 1663 Window child_return; 1664 unsigned int mask_return; 1665 blnr IsOk; 1666 int attempts = 0; 1667 1668#if VarFullScreen 1669 if (UseFullScreen) 1670#endif 1671#if MayFullScreen 1672 { 1673 h -= ViewHStart; 1674 v -= ViewVStart; 1675 } 1676#endif 1677 1678#if EnableMagnify 1679 if (UseMagnify) { 1680 h *= MyWindowScale; 1681 v *= MyWindowScale; 1682 } 1683#endif 1684 1685#if VarFullScreen 1686 if (UseFullScreen) 1687#endif 1688#if MayFullScreen 1689 { 1690 h += hOffset; 1691 v += vOffset; 1692 } 1693#endif 1694 1695 do { 1696 XWarpPointer(x_display, None, my_main_wind, 0, 0, 0, 0, h, v); 1697 XQueryPointer(x_display, my_main_wind, 1698 &root_return, &child_return, 1699 &root_x_return, &root_y_return, 1700 &NewMousePosh, &NewMousePosv, 1701 &mask_return); 1702 IsOk = (h == NewMousePosh) && (v == NewMousePosv); 1703 ++attempts; 1704 } while ((! IsOk) && (attempts < 10)); 1705 return IsOk; 1706} 1707#endif 1708 1709#if EnableFSMouseMotion 1710LOCALPROC StartSaveMouseMotion(void) 1711{ 1712 if (! HaveMouseMotion) { 1713 if (MyMoveMouse(ViewHStart + (ViewHSize / 2), 1714 ViewVStart + (ViewVSize / 2))) 1715 { 1716 SavedMouseH = ViewHStart + (ViewHSize / 2); 1717 SavedMouseV = ViewVStart + (ViewVSize / 2); 1718 HaveMouseMotion = trueblnr; 1719 } 1720 } 1721} 1722#endif 1723 1724#if EnableFSMouseMotion 1725LOCALPROC StopSaveMouseMotion(void) 1726{ 1727 if (HaveMouseMotion) { 1728 (void) MyMoveMouse(CurMouseH, CurMouseV); 1729 HaveMouseMotion = falseblnr; 1730 } 1731} 1732#endif 1733 1734/* cursor state */ 1735 1736#if EnableFSMouseMotion 1737LOCALPROC MyMouseConstrain(void) 1738{ 1739 si4b shiftdh; 1740 si4b shiftdv; 1741 1742 if (SavedMouseH < ViewHStart + (ViewHSize / 4)) { 1743 shiftdh = ViewHSize / 2; 1744 } else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) { 1745 shiftdh = - ViewHSize / 2; 1746 } else { 1747 shiftdh = 0; 1748 } 1749 if (SavedMouseV < ViewVStart + (ViewVSize / 4)) { 1750 shiftdv = ViewVSize / 2; 1751 } else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) { 1752 shiftdv = - ViewVSize / 2; 1753 } else { 1754 shiftdv = 0; 1755 } 1756 if ((shiftdh != 0) || (shiftdv != 0)) { 1757 SavedMouseH += shiftdh; 1758 SavedMouseV += shiftdv; 1759 if (! MyMoveMouse(SavedMouseH, SavedMouseV)) { 1760 HaveMouseMotion = falseblnr; 1761 } 1762 } 1763} 1764#endif 1765 1766LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv) 1767{ 1768 blnr ShouldHaveCursorHidden = trueblnr; 1769 1770#if VarFullScreen 1771 if (UseFullScreen) 1772#endif 1773#if MayFullScreen 1774 { 1775 NewMousePosh -= hOffset; 1776 NewMousePosv -= vOffset; 1777 } 1778#endif 1779 1780#if EnableMagnify 1781 if (UseMagnify) { 1782 NewMousePosh /= MyWindowScale; 1783 NewMousePosv /= MyWindowScale; 1784 } 1785#endif 1786 1787#if VarFullScreen 1788 if (UseFullScreen) 1789#endif 1790#if MayFullScreen 1791 { 1792 NewMousePosh += ViewHStart; 1793 NewMousePosv += ViewVStart; 1794 } 1795#endif 1796 1797#if EnableFSMouseMotion 1798 if (HaveMouseMotion) { 1799 MyMousePositionSetDelta(NewMousePosh - SavedMouseH, 1800 NewMousePosv - SavedMouseV); 1801 SavedMouseH = NewMousePosh; 1802 SavedMouseV = NewMousePosv; 1803 } else 1804#endif 1805 { 1806 if (NewMousePosh < 0) { 1807 NewMousePosh = 0; 1808 ShouldHaveCursorHidden = falseblnr; 1809 } else if (NewMousePosh >= vMacScreenWidth) { 1810 NewMousePosh = vMacScreenWidth - 1; 1811 ShouldHaveCursorHidden = falseblnr; 1812 } 1813 if (NewMousePosv < 0) { 1814 NewMousePosv = 0; 1815 ShouldHaveCursorHidden = falseblnr; 1816 } else if (NewMousePosv >= vMacScreenHeight) { 1817 NewMousePosv = vMacScreenHeight - 1; 1818 ShouldHaveCursorHidden = falseblnr; 1819 } 1820 1821#if VarFullScreen 1822 if (UseFullScreen) 1823#endif 1824#if MayFullScreen 1825 { 1826 ShouldHaveCursorHidden = trueblnr; 1827 } 1828#endif 1829 1830 /* if (ShouldHaveCursorHidden || CurMouseButton) */ 1831 /* 1832 for a game like arkanoid, would like mouse to still 1833 move even when outside window in one direction 1834 */ 1835 MyMousePositionSet(NewMousePosh, NewMousePosv); 1836 } 1837 1838 WantCursorHidden = ShouldHaveCursorHidden; 1839} 1840 1841LOCALPROC CheckMouseState(void) 1842{ 1843 int NewMousePosh; 1844 int NewMousePosv; 1845 int root_x_return; 1846 int root_y_return; 1847 Window root_return; 1848 Window child_return; 1849 unsigned int mask_return; 1850 1851 XQueryPointer(x_display, my_main_wind, 1852 &root_return, &child_return, 1853 &root_x_return, &root_y_return, 1854 &NewMousePosh, &NewMousePosv, 1855 &mask_return); 1856 MousePositionNotify(NewMousePosh, NewMousePosv); 1857} 1858 1859/* --- keyboard input --- */ 1860 1861/* 1862 translation table - X11 KeySym -> Mac key code 1863 1864 Used to create KC2MKC table (X11 key code -> Mac key code) 1865 1866 Includes effect of any key mapping set with the 1867 mini vmac '-km' compile time option. 1868 1869 The real CapsLock key needs special treatment, 1870 so use MKC_real_CapsLock here, 1871 which is later remapped to MKC_formac_CapsLock. 1872 1873 Ordered to match order of keycodes on Linux, the most 1874 common port using this X11 code, making the code using 1875 this table more efficient. 1876*/ 1877 1878/* 1879 The actual data is in the comments of this enum, 1880 from which MT2KeySym and MT2MKC are created by script. 1881*/ 1882enum { 1883 kMT_Escape, /* XK_Escape MKC_formac_Escape */ 1884 kMT_1, /* XK_1 MKC_1 */ 1885 kMT_2, /* XK_2 MKC_2 */ 1886 kMT_3, /* XK_3 MKC_3 */ 1887 kMT_4, /* XK_4 MKC_4 */ 1888 kMT_5, /* XK_5 MKC_5 */ 1889 kMT_6, /* XK_6 MKC_6 */ 1890 kMT_7, /* XK_7 MKC_7 */ 1891 kMT_8, /* XK_8 MKC_8 */ 1892 kMT_9, /* XK_9 MKC_9 */ 1893 kMT_0, /* XK_0 MKC_0 */ 1894 kMT_minus, /* XK_minus MKC_Minus */ 1895 kMT_underscore, /* XK_underscore MKC_Minus */ 1896 kMT_equal, /* XK_equal MKC_Equal */ 1897 kMT_plus, /* XK_plus MKC_Equal */ 1898 kMT_BackSpace, /* XK_BackSpace MKC_BackSpace */ 1899 kMT_Tab, /* XK_Tab MKC_Tab */ 1900 kMT_q, /* XK_q MKC_Q */ 1901 kMT_Q, /* XK_Q MKC_Q */ 1902 kMT_w, /* XK_w MKC_W */ 1903 kMT_W, /* XK_W MKC_W */ 1904 kMT_e, /* XK_e MKC_E */ 1905 kMT_E, /* XK_E MKC_E */ 1906 kMT_r, /* XK_r MKC_R */ 1907 kMT_R, /* XK_R MKC_R */ 1908 kMT_t, /* XK_t MKC_T */ 1909 kMT_T, /* XK_T MKC_T */ 1910 kMT_y, /* XK_y MKC_Y */ 1911 kMT_Y, /* XK_Y MKC_Y */ 1912 kMT_u, /* XK_u MKC_U */ 1913 kMT_U, /* XK_U MKC_U */ 1914 kMT_i, /* XK_i MKC_I */ 1915 kMT_I, /* XK_I MKC_I */ 1916 kMT_o, /* XK_o MKC_O */ 1917 kMT_O, /* XK_O MKC_O */ 1918 kMT_p, /* XK_p MKC_P */ 1919 kMT_P, /* XK_P MKC_P */ 1920 kMT_bracketleft, /* XK_bracketleft MKC_LeftBracket */ 1921 kMT_braceleft, /* XK_braceleft MKC_LeftBracket */ 1922 kMT_bracketright, /* XK_bracketright MKC_RightBracket */ 1923 kMT_braceright, /* XK_braceright MKC_RightBracket */ 1924 kMT_Return, /* XK_Return MKC_Return */ 1925 kMT_Control_L, /* XK_Control_L MKC_formac_Control */ 1926 kMT_a, /* XK_a MKC_A */ 1927 kMT_A, /* XK_A MKC_A */ 1928 kMT_s, /* XK_s MKC_S */ 1929 kMT_S, /* XK_S MKC_S */ 1930 kMT_d, /* XK_d MKC_D */ 1931 kMT_D, /* XK_D MKC_D */ 1932 kMT_f, /* XK_f MKC_F */ 1933 kMT_F, /* XK_F MKC_F */ 1934 kMT_g, /* XK_g MKC_G */ 1935 kMT_G, /* XK_G MKC_G */ 1936 kMT_h, /* XK_h MKC_H */ 1937 kMT_H, /* XK_H MKC_H */ 1938 kMT_j, /* XK_j MKC_J */ 1939 kMT_J, /* XK_J MKC_J */ 1940 kMT_k, /* XK_k MKC_K */ 1941 kMT_K, /* XK_K MKC_K */ 1942 kMT_l, /* XK_l MKC_L */ 1943 kMT_L, /* XK_L MKC_L */ 1944 kMT_semicolon, /* XK_semicolon MKC_SemiColon */ 1945 kMT_colon, /* XK_colon MKC_SemiColon */ 1946 kMT_apostrophe, /* XK_apostrophe MKC_SingleQuote */ 1947 kMT_quotedbl, /* XK_quotedbl MKC_SingleQuote */ 1948 kMT_grave, /* XK_grave MKC_formac_Grave */ 1949 kMT_asciitilde, /* XK_asciitilde MKC_formac_Grave */ 1950 kMT_Shift_L, /* XK_Shift_L MKC_formac_Shift */ 1951 kMT_backslash, /* XK_backslash MKC_formac_BackSlash */ 1952 kMT_bar, /* XK_bar MKC_formac_BackSlash */ 1953 kMT_z, /* XK_z MKC_Z */ 1954 kMT_Z, /* XK_Z MKC_Z */ 1955 kMT_x, /* XK_x MKC_X */ 1956 kMT_X, /* XK_X MKC_X */ 1957 kMT_c, /* XK_c MKC_C */ 1958 kMT_C, /* XK_C MKC_C */ 1959 kMT_v, /* XK_v MKC_V */ 1960 kMT_V, /* XK_V MKC_V */ 1961 kMT_b, /* XK_b MKC_B */ 1962 kMT_B, /* XK_B MKC_B */ 1963 kMT_n, /* XK_n MKC_N */ 1964 kMT_N, /* XK_N MKC_N */ 1965 kMT_m, /* XK_m MKC_M */ 1966 kMT_M, /* XK_M MKC_M */ 1967 kMT_comma, /* XK_comma MKC_Comma */ 1968 kMT_period, /* XK_period MKC_Period */ 1969 kMT_greater, /* XK_greater MKC_Period */ 1970 kMT_slash, /* XK_slash MKC_formac_Slash */ 1971 kMT_question, /* XK_question MKC_formac_Slash */ 1972 kMT_Shift_R, /* XK_Shift_R MKC_formac_RShift */ 1973 kMT_KP_Multiply, /* XK_KP_Multiply MKC_KPMultiply */ 1974 kMT_Alt_L, /* XK_Alt_L MKC_formac_Command */ 1975 kMT_space, /* XK_space MKC_Space */ 1976 kMT_Caps_Lock, /* XK_Caps_Lock MKC_real_CapsLock */ 1977 kMT_F1, /* XK_F1 MKC_formac_F1 */ 1978 kMT_F2, /* XK_F2 MKC_formac_F2 */ 1979 kMT_F3, /* XK_F3 MKC_formac_F3 */ 1980 kMT_F4, /* XK_F4 MKC_formac_F4 */ 1981 kMT_F5, /* XK_F5 MKC_formac_F5 */ 1982 kMT_F6, /* XK_F6 MKC_F6 */ 1983 kMT_F7, /* XK_F7 MKC_F7 */ 1984 kMT_F8, /* XK_F8 MKC_F8 */ 1985 kMT_F9, /* XK_F9 MKC_F9 */ 1986 kMT_F10, /* XK_F10 MKC_F10 */ 1987 kMT_Num_Lock, /* XK_Num_Lock MKC_Clear */ 1988#ifdef XK_Scroll_Lock 1989 kMT_Scroll_Lock, /* XK_Scroll_Lock MKC_ScrollLock */ 1990#endif 1991#ifdef XK_F14 1992 kMT_F14, /* XK_F14 MKC_ScrollLock */ 1993#endif 1994 1995 kMT_KP_7, /* XK_KP_7 MKC_KP7 */ 1996#ifdef XK_KP_Home 1997 kMT_KP_Home, /* XK_KP_Home MKC_KP7 */ 1998#endif 1999 2000 kMT_KP_8, /* XK_KP_8 MKC_KP8 */ 2001#ifdef XK_KP_Up 2002 kMT_KP_Up, /* XK_KP_Up MKC_KP8 */ 2003#endif 2004 2005 kMT_KP_9, /* XK_KP_9 MKC_KP9 */ 2006#ifdef XK_KP_Page_Up 2007 kMT_KP_Page_Up, /* XK_KP_Page_Up MKC_KP9 */ 2008#else 2009#ifdef XK_KP_Prior 2010 kMT_KP_Prior, /* XK_KP_Prior MKC_KP9 */ 2011#endif 2012#endif 2013 2014 kMT_KP_Subtract, /* XK_KP_Subtract MKC_KPSubtract */ 2015 2016 kMT_KP_4, /* XK_KP_4 MKC_KP4 */ 2017#ifdef XK_KP_Left 2018 kMT_KP_Left, /* XK_KP_Left MKC_KP4 */ 2019#endif 2020 2021 kMT_KP_5, /* XK_KP_5 MKC_KP5 */ 2022#ifdef XK_KP_Begin 2023 kMT_KP_Begin, /* XK_KP_Begin MKC_KP5 */ 2024#endif 2025 2026 kMT_KP_6, /* XK_KP_6 MKC_KP6 */ 2027#ifdef XK_KP_Right 2028 kMT_KP_Right, /* XK_KP_Right MKC_KP6 */ 2029#endif 2030 2031 kMT_KP_Add, /* XK_KP_Add MKC_KPAdd */ 2032 2033 kMT_KP_1, /* XK_KP_1 MKC_KP1 */ 2034#ifdef XK_KP_End 2035 kMT_KP_End, /* XK_KP_End MKC_KP1 */ 2036#endif 2037 2038 kMT_KP_2, /* XK_KP_2 MKC_KP2 */ 2039#ifdef XK_KP_Down 2040 kMT_KP_Down, /* XK_KP_Down MKC_KP2 */ 2041#endif 2042 2043 kMT_KP_3, /* XK_KP_3 MKC_KP3 */ 2044#ifdef XK_Page_Down 2045 kMT_KP_Page_Down, /* XK_KP_Page_Down MKC_KP3 */ 2046#else 2047#ifdef XK_KP_Next 2048 kMT_KP_Next, /* XK_KP_Next MKC_KP3 */ 2049#endif 2050#endif 2051 2052 kMT_KP_0, /* XK_KP_0 MKC_KP0 */ 2053#ifdef XK_KP_Insert 2054 kMT_KP_Insert, /* XK_KP_Insert MKC_KP0 */ 2055#endif 2056#ifdef XK_KP_Delete 2057 kMT_KP_Delete, /* XK_KP_Delete MKC_Decimal */ 2058#endif 2059 2060 /* XK_ISO_Level3_Shift */ 2061 /* nothing */ 2062#ifdef XK_less 2063 kMT_less, /* XK_less MKC_Comma */ 2064#endif 2065 kMT_F11, /* XK_F11 MKC_F11 */ 2066 kMT_F12, /* XK_F12 MKC_F12 */ 2067 /* nothing */ 2068 /* XK_Katakana */ 2069 /* XK_Hiragana */ 2070 /* XK_Henkan */ 2071 /* XK_Hiragana_Katakana */ 2072 /* XK_Muhenkan */ 2073 /* nothing */ 2074 kMT_KP_Enter, /* XK_KP_Enter MKC_formac_Enter */ 2075 kMT_Control_R, /* XK_Control_R MKC_formac_RControl */ 2076 kMT_KP_Divide, /* XK_KP_Divide MKC_KPDevide */ 2077#ifdef XK_Print 2078 kMT_Print, /* XK_Print MKC_Print */ 2079#endif 2080 kMT_Alt_R, /* XK_Alt_R MKC_formac_RCommand */ 2081 /* XK_Linefeed */ 2082#ifdef XK_Home 2083 kMT_Home, /* XK_Home MKC_formac_Home */ 2084#endif 2085 kMT_Up, /* XK_Up MKC_Up */ 2086 2087#ifdef XK_Page_Up 2088 kMT_Page_Up, /* XK_Page_Up MKC_formac_PageUp */ 2089#else 2090#ifdef XK_Prior 2091 kMT_Prior, /* XK_Prior MKC_formac_PageUp */ 2092#endif 2093#endif 2094 2095 kMT_Left, /* XK_Left MKC_Left */ 2096 kMT_Right, /* XK_Right MKC_Right */ 2097#ifdef XK_End 2098 kMT_End, /* XK_End MKC_formac_End */ 2099#endif 2100 kMT_Down, /* XK_Down MKC_Down */ 2101 2102#ifdef XK_Page_Down 2103 kMT_Page_Down, /* XK_Page_Down MKC_formac_PageDown */ 2104#else 2105#ifdef XK_Next 2106 kMT_Next, /* XK_Next MKC_formac_PageDown */ 2107#endif 2108#endif 2109 2110#ifdef XK_Insert 2111 kMT_Insert, /* XK_Insert MKC_formac_Help */ 2112#endif 2113#ifdef XK_Delete 2114 kMT_Delete, /* XK_Delete MKC_formac_ForwardDel */ 2115#endif 2116 /* nothing */ 2117 /* ? */ 2118 /* ? */ 2119 /* ? */ 2120 /* ? */ 2121 kMT_KP_Equal, /* XK_KP_Equal MKC_KPEqual */ 2122 /* XK_plusminus */ 2123#ifdef XK_Pause 2124 kMT_Pause, /* XK_Pause MKC_Pause */ 2125#endif 2126#ifdef XK_F15 2127 kMT_F15, /* XK_F15 MKC_Pause */ 2128#endif 2129 /* ? */ 2130 kMT_KP_Decimal, /* XK_KP_Decimal MKC_Decimal */ 2131 /* XK_Hangul */ 2132 /* XK_Hangul_Hanja */ 2133 /* nothing */ 2134 kMT_Super_L, /* XK_Super_L MKC_formac_Option */ 2135 kMT_Super_R, /* XK_Super_R MKC_formac_ROption */ 2136 kMT_Menu, /* XK_Menu MKC_formac_Option */ 2137 /* XK_Cancel */ 2138 /* XK_Redo */ 2139 /* ? */ 2140 /* XK_Undo */ 2141 /* ? */ 2142 /* ? */ 2143 /* ? */ 2144 /* ? */ 2145 /* XK_Find */ 2146 /* ? */ 2147#ifdef XK_Help 2148 kMT_Help, /* XK_Help MKC_formac_Help */ 2149#endif 2150 /* ? */ 2151 /* ? */ 2152 /* nothing */ 2153 /* ? */ 2154 /* ? */ 2155 /* ? */ 2156 /* ? */ 2157 /* nothing */ 2158 2159 /* XK_parenleft */ 2160 /* XK_parenright */ 2161 2162 /* XK_Mode_switch */ 2163 2164 2165 2166 kMT_Meta_L, /* XK_Meta_L MKC_formac_Command */ 2167 kMT_Meta_R, /* XK_Meta_R MKC_formac_RCommand */ 2168 2169 kMT_Mode_switch, /* XK_Mode_switch MKC_formac_Option */ 2170 kMT_Hyper_L, /* XK_Hyper_L MKC_formac_Option */ 2171 kMT_Hyper_R, /* XK_Hyper_R MKC_formac_ROption */ 2172 2173 kMT_F13, /* XK_F13 MKC_formac_Option */ 2174 /* 2175 seen being used in Mandrake Linux 9.2 2176 for windows key 2177 */ 2178 2179 kNumMTs 2180}; 2181 2182/* 2183 MT2KeySym was generated by a script from 2184 enum and comments above. 2185*/ 2186LOCALVAR const KeySym MT2KeySym[kNumMTs + 1] = { 2187 XK_Escape, /* kMT_Escape */ 2188 XK_1, /* kMT_1 */ 2189 XK_2, /* kMT_2 */ 2190 XK_3, /* kMT_3 */ 2191 XK_4, /* kMT_4 */ 2192 XK_5, /* kMT_5 */ 2193 XK_6, /* kMT_6 */ 2194 XK_7, /* kMT_7 */ 2195 XK_8, /* kMT_8 */ 2196 XK_9, /* kMT_9 */ 2197 XK_0, /* kMT_0 */ 2198 XK_minus, /* kMT_minus */ 2199 XK_underscore, /* kMT_underscore */ 2200 XK_equal, /* kMT_equal */ 2201 XK_plus, /* kMT_plus */ 2202 XK_BackSpace, /* kMT_BackSpace */ 2203 XK_Tab, /* kMT_Tab */ 2204 XK_q, /* kMT_q */ 2205 XK_Q, /* kMT_Q */ 2206 XK_w, /* kMT_w */ 2207 XK_W, /* kMT_W */ 2208 XK_e, /* kMT_e */ 2209 XK_E, /* kMT_E */ 2210 XK_r, /* kMT_r */ 2211 XK_R, /* kMT_R */ 2212 XK_t, /* kMT_t */ 2213 XK_T, /* kMT_T */ 2214 XK_y, /* kMT_y */ 2215 XK_Y, /* kMT_Y */ 2216 XK_u, /* kMT_u */ 2217 XK_U, /* kMT_U */ 2218 XK_i, /* kMT_i */ 2219 XK_I, /* kMT_I */ 2220 XK_o, /* kMT_o */ 2221 XK_O, /* kMT_O */ 2222 XK_p, /* kMT_p */ 2223 XK_P, /* kMT_P */ 2224 XK_bracketleft, /* kMT_bracketleft */ 2225 XK_braceleft, /* kMT_braceleft */ 2226 XK_bracketright, /* kMT_bracketright */ 2227 XK_braceright, /* kMT_braceright */ 2228 XK_Return, /* kMT_Return */ 2229 XK_Control_L, /* kMT_Control_L */ 2230 XK_a, /* kMT_a */ 2231 XK_A, /* kMT_A */ 2232 XK_s, /* kMT_s */ 2233 XK_S, /* kMT_S */ 2234 XK_d, /* kMT_d */ 2235 XK_D, /* kMT_D */ 2236 XK_f, /* kMT_f */ 2237 XK_F, /* kMT_F */ 2238 XK_g, /* kMT_g */ 2239 XK_G, /* kMT_G */ 2240 XK_h, /* kMT_h */ 2241 XK_H, /* kMT_H */ 2242 XK_j, /* kMT_j */ 2243 XK_J, /* kMT_J */ 2244 XK_k, /* kMT_k */ 2245 XK_K, /* kMT_K */ 2246 XK_l, /* kMT_l */ 2247 XK_L, /* kMT_L */ 2248 XK_semicolon, /* kMT_semicolon */ 2249 XK_colon, /* kMT_colon */ 2250 XK_apostrophe, /* kMT_apostrophe */ 2251 XK_quotedbl, /* kMT_quotedbl */ 2252 XK_grave, /* kMT_grave */ 2253 XK_asciitilde, /* kMT_asciitilde */ 2254 XK_Shift_L, /* kMT_Shift_L */ 2255 XK_backslash, /* kMT_backslash */ 2256 XK_bar, /* kMT_bar */ 2257 XK_z, /* kMT_z */ 2258 XK_Z, /* kMT_Z */ 2259 XK_x, /* kMT_x */ 2260 XK_X, /* kMT_X */ 2261 XK_c, /* kMT_c */ 2262 XK_C, /* kMT_C */ 2263 XK_v, /* kMT_v */ 2264 XK_V, /* kMT_V */ 2265 XK_b, /* kMT_b */ 2266 XK_B, /* kMT_B */ 2267 XK_n, /* kMT_n */ 2268 XK_N, /* kMT_N */ 2269 XK_m, /* kMT_m */ 2270 XK_M, /* kMT_M */ 2271 XK_comma, /* kMT_comma */ 2272 XK_period, /* kMT_period */ 2273 XK_greater, /* kMT_greater */ 2274 XK_slash, /* kMT_slash */ 2275 XK_question, /* kMT_question */ 2276 XK_Shift_R, /* kMT_Shift_R */ 2277 XK_KP_Multiply, /* kMT_KP_Multiply */ 2278 XK_Alt_L, /* kMT_Alt_L */ 2279 XK_space, /* kMT_space */ 2280 XK_Caps_Lock, /* kMT_Caps_Lock */ 2281 XK_F1, /* kMT_F1 */ 2282 XK_F2, /* kMT_F2 */ 2283 XK_F3, /* kMT_F3 */ 2284 XK_F4, /* kMT_F4 */ 2285 XK_F5, /* kMT_F5 */ 2286 XK_F6, /* kMT_F6 */ 2287 XK_F7, /* kMT_F7 */ 2288 XK_F8, /* kMT_F8 */ 2289 XK_F9, /* kMT_F9 */ 2290 XK_F10, /* kMT_F10 */ 2291 XK_Num_Lock, /* kMT_Num_Lock */ 2292#ifdef XK_Scroll_Lock 2293 XK_Scroll_Lock, /* kMT_Scroll_Lock */ 2294#endif 2295#ifdef XK_F14 2296 XK_F14, /* kMT_F14 */ 2297#endif 2298 2299 XK_KP_7, /* kMT_KP_7 */ 2300#ifdef XK_KP_Home 2301 XK_KP_Home, /* kMT_KP_Home */ 2302#endif 2303 2304 XK_KP_8, /* kMT_KP_8 */ 2305#ifdef XK_KP_Up 2306 XK_KP_Up, /* kMT_KP_Up */ 2307#endif 2308 2309 XK_KP_9, /* kMT_KP_9 */ 2310#ifdef XK_KP_Page_Up 2311 XK_KP_Page_Up, /* kMT_KP_Page_Up */ 2312#else 2313#ifdef XK_KP_Prior 2314 XK_KP_Prior, /* kMT_KP_Prior */ 2315#endif 2316#endif 2317 2318 XK_KP_Subtract, /* kMT_KP_Subtract */ 2319 2320 XK_KP_4, /* kMT_KP_4 */ 2321#ifdef XK_KP_Left 2322 XK_KP_Left, /* kMT_KP_Left */ 2323#endif 2324 2325 XK_KP_5, /* kMT_KP_5 */ 2326#ifdef XK_KP_Begin 2327 XK_KP_Begin, /* kMT_KP_Begin */ 2328#endif 2329 2330 XK_KP_6, /* kMT_KP_6 */ 2331#ifdef XK_KP_Right 2332 XK_KP_Right, /* kMT_KP_Right */ 2333#endif 2334 2335 XK_KP_Add, /* kMT_KP_Add */ 2336 2337 XK_KP_1, /* kMT_KP_1 */ 2338#ifdef XK_KP_End 2339 XK_KP_End, /* kMT_KP_End */ 2340#endif 2341 2342 XK_KP_2, /* kMT_KP_2 */ 2343#ifdef XK_KP_Down 2344 XK_KP_Down, /* kMT_KP_Down */ 2345#endif 2346 2347 XK_KP_3, /* kMT_KP_3 */ 2348#ifdef XK_Page_Down 2349 XK_KP_Page_Down, /* kMT_KP_Page_Down */ 2350#else 2351#ifdef XK_KP_Next 2352 XK_KP_Next, /* kMT_KP_Next */ 2353#endif 2354#endif 2355 2356 XK_KP_0, /* kMT_KP_0 */ 2357#ifdef XK_KP_Insert 2358 XK_KP_Insert, /* kMT_KP_Insert */ 2359#endif 2360#ifdef XK_KP_Delete 2361 XK_KP_Delete, /* kMT_KP_Delete */ 2362#endif 2363 2364 /* XK_ISO_Level3_Shift */ 2365 /* nothing */ 2366#ifdef XK_less 2367 XK_less, /* kMT_less */ 2368#endif 2369 XK_F11, /* kMT_F11 */ 2370 XK_F12, /* kMT_F12 */ 2371 /* nothing */ 2372 /* XK_Katakana */ 2373 /* XK_Hiragana */ 2374 /* XK_Henkan */ 2375 /* XK_Hiragana_Katakana */ 2376 /* XK_Muhenkan */ 2377 /* nothing */ 2378 XK_KP_Enter, /* kMT_KP_Enter */ 2379 XK_Control_R, /* kMT_Control_R */ 2380 XK_KP_Divide, /* kMT_KP_Divide */ 2381#ifdef XK_Print 2382 XK_Print, /* kMT_Print */ 2383#endif 2384 XK_Alt_R, /* kMT_Alt_R */ 2385 /* XK_Linefeed */ 2386#ifdef XK_Home 2387 XK_Home, /* kMT_Home */ 2388#endif 2389 XK_Up, /* kMT_Up */ 2390 2391#ifdef XK_Page_Up 2392 XK_Page_Up, /* kMT_Page_Up */ 2393#else 2394#ifdef XK_Prior 2395 XK_Prior, /* kMT_Prior */ 2396#endif 2397#endif 2398 2399 XK_Left, /* kMT_Left */ 2400 XK_Right, /* kMT_Right */ 2401#ifdef XK_End 2402 XK_End, /* kMT_End */ 2403#endif 2404 XK_Down, /* kMT_Down */ 2405 2406#ifdef XK_Page_Down 2407 XK_Page_Down, /* kMT_Page_Down */ 2408#else 2409#ifdef XK_Next 2410 XK_Next, /* kMT_Next */ 2411#endif 2412#endif 2413 2414#ifdef XK_Insert 2415 XK_Insert, /* kMT_Insert */ 2416#endif 2417#ifdef XK_Delete 2418 XK_Delete, /* kMT_Delete */ 2419#endif 2420 /* nothing */ 2421 /* ? */ 2422 /* ? */ 2423 /* ? */ 2424 /* ? */ 2425 XK_KP_Equal, /* kMT_KP_Equal */ 2426 /* XK_plusminus */ 2427#ifdef XK_Pause 2428 XK_Pause, /* kMT_Pause */ 2429#endif 2430#ifdef XK_F15 2431 XK_F15, /* kMT_F15 */ 2432#endif 2433 /* ? */ 2434 XK_KP_Decimal, /* kMT_KP_Decimal */ 2435 /* XK_Hangul */ 2436 /* XK_Hangul_Hanja */ 2437 /* nothing */ 2438 XK_Super_L, /* kMT_Super_L */ 2439 XK_Super_R, /* kMT_Super_R */ 2440 XK_Menu, /* kMT_Menu */ 2441 /* XK_Cancel */ 2442 /* XK_Redo */ 2443 /* ? */ 2444 /* XK_Undo */ 2445 /* ? */ 2446 /* ? */ 2447 /* ? */ 2448 /* ? */ 2449 /* XK_Find */ 2450 /* ? */ 2451#ifdef XK_Help 2452 XK_Help, /* kMT_Help */ 2453#endif 2454 /* ? */ 2455 /* ? */ 2456 /* nothing */ 2457 /* ? */ 2458 /* ? */ 2459 /* ? */ 2460 /* ? */ 2461 /* nothing */ 2462 2463 /* XK_parenleft */ 2464 /* XK_parenright */ 2465 2466 /* XK_Mode_switch */ 2467 2468 2469 2470 XK_Meta_L, /* kMT_Meta_L */ 2471 XK_Meta_R, /* kMT_Meta_R */ 2472 2473 XK_Mode_switch, /* kMT_Mode_switch */ 2474 XK_Hyper_L, /* kMT_Hyper_L */ 2475 XK_Hyper_R, /* kMT_Hyper_R */ 2476 2477 XK_F13, /* kMT_F13 */ 2478 /* 2479 seen being used in Mandrake Linux 9.2 2480 for windows key 2481 */ 2482 2483 0 /* just so last above line can end in ',' */ 2484}; 2485 2486/* 2487 MT2MKC was generated by a script from 2488 enum and comments above. 2489*/ 2490LOCALVAR const ui3r MT2MKC[kNumMTs + 1] = { 2491 MKC_formac_Escape, /* kMT_Escape */ 2492 MKC_1, /* kMT_1 */ 2493 MKC_2, /* kMT_2 */ 2494 MKC_3, /* kMT_3 */ 2495 MKC_4, /* kMT_4 */ 2496 MKC_5, /* kMT_5 */ 2497 MKC_6, /* kMT_6 */ 2498 MKC_7, /* kMT_7 */ 2499 MKC_8, /* kMT_8 */ 2500 MKC_9, /* kMT_9 */ 2501 MKC_0, /* kMT_0 */ 2502 MKC_Minus, /* kMT_minus */ 2503 MKC_Minus, /* kMT_underscore */ 2504 MKC_Equal, /* kMT_equal */ 2505 MKC_Equal, /* kMT_plus */ 2506 MKC_BackSpace, /* kMT_BackSpace */ 2507 MKC_Tab, /* kMT_Tab */ 2508 MKC_Q, /* kMT_q */ 2509 MKC_Q, /* kMT_Q */ 2510 MKC_W, /* kMT_w */ 2511 MKC_W, /* kMT_W */ 2512 MKC_E, /* kMT_e */ 2513 MKC_E, /* kMT_E */ 2514 MKC_R, /* kMT_r */ 2515 MKC_R, /* kMT_R */ 2516 MKC_T, /* kMT_t */ 2517 MKC_T, /* kMT_T */ 2518 MKC_Y, /* kMT_y */ 2519 MKC_Y, /* kMT_Y */ 2520 MKC_U, /* kMT_u */ 2521 MKC_U, /* kMT_U */ 2522 MKC_I, /* kMT_i */ 2523 MKC_I, /* kMT_I */ 2524 MKC_O, /* kMT_o */ 2525 MKC_O, /* kMT_O */ 2526 MKC_P, /* kMT_p */ 2527 MKC_P, /* kMT_P */ 2528 MKC_LeftBracket, /* kMT_bracketleft */ 2529 MKC_LeftBracket, /* kMT_braceleft */ 2530 MKC_RightBracket, /* kMT_bracketright */ 2531 MKC_RightBracket, /* kMT_braceright */ 2532 MKC_Return, /* kMT_Return */ 2533 MKC_formac_Control, /* kMT_Control_L */ 2534 MKC_A, /* kMT_a */ 2535 MKC_A, /* kMT_A */ 2536 MKC_S, /* kMT_s */ 2537 MKC_S, /* kMT_S */ 2538 MKC_D, /* kMT_d */ 2539 MKC_D, /* kMT_D */ 2540 MKC_F, /* kMT_f */ 2541 MKC_F, /* kMT_F */ 2542 MKC_G, /* kMT_g */ 2543 MKC_G, /* kMT_G */ 2544 MKC_H, /* kMT_h */ 2545 MKC_H, /* kMT_H */ 2546 MKC_J, /* kMT_j */ 2547 MKC_J, /* kMT_J */ 2548 MKC_K, /* kMT_k */ 2549 MKC_K, /* kMT_K */ 2550 MKC_L, /* kMT_l */ 2551 MKC_L, /* kMT_L */ 2552 MKC_SemiColon, /* kMT_semicolon */ 2553 MKC_SemiColon, /* kMT_colon */ 2554 MKC_SingleQuote, /* kMT_apostrophe */ 2555 MKC_SingleQuote, /* kMT_quotedbl */ 2556 MKC_formac_Grave, /* kMT_grave */ 2557 MKC_formac_Grave, /* kMT_asciitilde */ 2558 MKC_formac_Shift, /* kMT_Shift_L */ 2559 MKC_formac_BackSlash, /* kMT_backslash */ 2560 MKC_formac_BackSlash, /* kMT_bar */ 2561 MKC_Z, /* kMT_z */ 2562 MKC_Z, /* kMT_Z */ 2563 MKC_X, /* kMT_x */ 2564 MKC_X, /* kMT_X */ 2565 MKC_C, /* kMT_c */ 2566 MKC_C, /* kMT_C */ 2567 MKC_V, /* kMT_v */ 2568 MKC_V, /* kMT_V */ 2569 MKC_B, /* kMT_b */ 2570 MKC_B, /* kMT_B */ 2571 MKC_N, /* kMT_n */ 2572 MKC_N, /* kMT_N */ 2573 MKC_M, /* kMT_m */ 2574 MKC_M, /* kMT_M */ 2575 MKC_Comma, /* kMT_comma */ 2576 MKC_Period, /* kMT_period */ 2577 MKC_Period, /* kMT_greater */ 2578 MKC_formac_Slash, /* kMT_slash */ 2579 MKC_formac_Slash, /* kMT_question */ 2580 MKC_formac_RShift, /* kMT_Shift_R */ 2581 MKC_KPMultiply, /* kMT_KP_Multiply */ 2582 MKC_formac_Command, /* kMT_Alt_L */ 2583 MKC_Space, /* kMT_space */ 2584 MKC_real_CapsLock, /* kMT_Caps_Lock */ 2585 MKC_formac_F1, /* kMT_F1 */ 2586 MKC_formac_F2, /* kMT_F2 */ 2587 MKC_formac_F3, /* kMT_F3 */ 2588 MKC_formac_F4, /* kMT_F4 */ 2589 MKC_formac_F5, /* kMT_F5 */ 2590 MKC_F6, /* kMT_F6 */ 2591 MKC_F7, /* kMT_F7 */ 2592 MKC_F8, /* kMT_F8 */ 2593 MKC_F9, /* kMT_F9 */ 2594 MKC_F10, /* kMT_F10 */ 2595 MKC_Clear, /* kMT_Num_Lock */ 2596#ifdef XK_Scroll_Lock 2597 MKC_ScrollLock, /* kMT_Scroll_Lock */ 2598#endif 2599#ifdef XK_F14 2600 MKC_ScrollLock, /* kMT_F14 */ 2601#endif 2602 2603 MKC_KP7, /* kMT_KP_7 */ 2604#ifdef XK_KP_Home 2605 MKC_KP7, /* kMT_KP_Home */ 2606#endif 2607 2608 MKC_KP8, /* kMT_KP_8 */ 2609#ifdef XK_KP_Up 2610 MKC_KP8, /* kMT_KP_Up */ 2611#endif 2612 2613 MKC_KP9, /* kMT_KP_9 */ 2614#ifdef XK_KP_Page_Up 2615 MKC_KP9, /* kMT_KP_Page_Up */ 2616#else 2617#ifdef XK_KP_Prior 2618 MKC_KP9, /* kMT_KP_Prior */ 2619#endif 2620#endif 2621 2622 MKC_KPSubtract, /* kMT_KP_Subtract */ 2623 2624 MKC_KP4, /* kMT_KP_4 */ 2625#ifdef XK_KP_Left 2626 MKC_KP4, /* kMT_KP_Left */ 2627#endif 2628 2629 MKC_KP5, /* kMT_KP_5 */ 2630#ifdef XK_KP_Begin 2631 MKC_KP5, /* kMT_KP_Begin */ 2632#endif 2633 2634 MKC_KP6, /* kMT_KP_6 */ 2635#ifdef XK_KP_Right 2636 MKC_KP6, /* kMT_KP_Right */ 2637#endif 2638 2639 MKC_KPAdd, /* kMT_KP_Add */ 2640 2641 MKC_KP1, /* kMT_KP_1 */ 2642#ifdef XK_KP_End 2643 MKC_KP1, /* kMT_KP_End */ 2644#endif 2645 2646 MKC_KP2, /* kMT_KP_2 */ 2647#ifdef XK_KP_Down 2648 MKC_KP2, /* kMT_KP_Down */ 2649#endif 2650 2651 MKC_KP3, /* kMT_KP_3 */ 2652#ifdef XK_Page_Down 2653 MKC_KP3, /* kMT_KP_Page_Down */ 2654#else 2655#ifdef XK_KP_Next 2656 MKC_KP3, /* kMT_KP_Next */ 2657#endif 2658#endif 2659 2660 MKC_KP0, /* kMT_KP_0 */ 2661#ifdef XK_KP_Insert 2662 MKC_KP0, /* kMT_KP_Insert */ 2663#endif 2664#ifdef XK_KP_Delete 2665 MKC_Decimal, /* kMT_KP_Delete */ 2666#endif 2667 2668 /* XK_ISO_Level3_Shift */ 2669 /* nothing */ 2670#ifdef XK_less 2671 MKC_Comma, /* kMT_less */ 2672#endif 2673 MKC_F11, /* kMT_F11 */ 2674 MKC_F12, /* kMT_F12 */ 2675 /* nothing */ 2676 /* XK_Katakana */ 2677 /* XK_Hiragana */ 2678 /* XK_Henkan */ 2679 /* XK_Hiragana_Katakana */ 2680 /* XK_Muhenkan */ 2681 /* nothing */ 2682 MKC_formac_Enter, /* kMT_KP_Enter */ 2683 MKC_formac_RControl, /* kMT_Control_R */ 2684 MKC_KPDevide, /* kMT_KP_Divide */ 2685#ifdef XK_Print 2686 MKC_Print, /* kMT_Print */ 2687#endif 2688 MKC_formac_RCommand, /* kMT_Alt_R */ 2689 /* XK_Linefeed */ 2690#ifdef XK_Home 2691 MKC_formac_Home, /* kMT_Home */ 2692#endif 2693 MKC_Up, /* kMT_Up */ 2694 2695#ifdef XK_Page_Up 2696 MKC_formac_PageUp, /* kMT_Page_Up */ 2697#else 2698#ifdef XK_Prior 2699 MKC_formac_PageUp, /* kMT_Prior */ 2700#endif 2701#endif 2702 2703 MKC_Left, /* kMT_Left */ 2704 MKC_Right, /* kMT_Right */ 2705#ifdef XK_End 2706 MKC_formac_End, /* kMT_End */ 2707#endif 2708 MKC_Down, /* kMT_Down */ 2709 2710#ifdef XK_Page_Down 2711 MKC_formac_PageDown, /* kMT_Page_Down */ 2712#else 2713#ifdef XK_Next 2714 MKC_formac_PageDown, /* kMT_Next */ 2715#endif 2716#endif 2717 2718#ifdef XK_Insert 2719 MKC_formac_Help, /* kMT_Insert */ 2720#endif 2721#ifdef XK_Delete 2722 MKC_formac_ForwardDel, /* kMT_Delete */ 2723#endif 2724 /* nothing */ 2725 /* ? */ 2726 /* ? */ 2727 /* ? */ 2728 /* ? */ 2729 MKC_KPEqual, /* kMT_KP_Equal */ 2730 /* XK_plusminus */ 2731#ifdef XK_Pause 2732 MKC_Pause, /* kMT_Pause */ 2733#endif 2734#ifdef XK_F15 2735 MKC_Pause, /* kMT_F15 */ 2736#endif 2737 /* ? */ 2738 MKC_Decimal, /* kMT_KP_Decimal */ 2739 /* XK_Hangul */ 2740 /* XK_Hangul_Hanja */ 2741 /* nothing */ 2742 MKC_formac_Option, /* kMT_Super_L */ 2743 MKC_formac_ROption, /* kMT_Super_R */ 2744 MKC_formac_Option, /* kMT_Menu */ 2745 /* XK_Cancel */ 2746 /* XK_Redo */ 2747 /* ? */ 2748 /* XK_Undo */ 2749 /* ? */ 2750 /* ? */ 2751 /* ? */ 2752 /* ? */ 2753 /* XK_Find */ 2754 /* ? */ 2755#ifdef XK_Help 2756 MKC_formac_Help, /* kMT_Help */ 2757#endif 2758 /* ? */ 2759 /* ? */ 2760 /* nothing */ 2761 /* ? */ 2762 /* ? */ 2763 /* ? */ 2764 /* ? */ 2765 /* nothing */ 2766 2767 /* XK_parenleft */ 2768 /* XK_parenright */ 2769 2770 /* XK_Mode_switch */ 2771 2772 2773 2774 MKC_formac_Command, /* kMT_Meta_L */ 2775 MKC_formac_RCommand, /* kMT_Meta_R */ 2776 2777 MKC_formac_Option, /* kMT_Mode_switch */ 2778 MKC_formac_Option, /* kMT_Hyper_L */ 2779 MKC_formac_ROption, /* kMT_Hyper_R */ 2780 2781 MKC_formac_Option, /* kMT_F13 */ 2782 /* 2783 seen being used in Mandrake Linux 9.2 2784 for windows key 2785 */ 2786 2787 0 /* just so last above line can end in ',' */ 2788}; 2789 2790LOCALVAR ui3b KC2MKC[256]; 2791 /* 2792 translate X11 key code to Macintosh key code 2793 */ 2794 2795#define KMInit_dolog (dbglog_HAVE && 0) 2796 2797LOCALFUNC blnr KC2MKCInit(void) 2798{ 2799 int i; 2800 int j; 2801 int last_j; 2802 int first_keycode; 2803 int last_keycode; 2804 int keysyms_per_keycode; 2805 KeySym *KeyMap; 2806 KeySym MaxUsedKeySym; 2807 2808 /* 2809 In Linux, observe that most KeySyms not 2810 found in our translation table are large. 2811 So saves time to find largest KeySym we 2812 are interested in. 2813 */ 2814 MaxUsedKeySym = 0; 2815 for (j = 0; j < kNumMTs; j++) { 2816 KeySym x = MT2KeySym[j]; 2817 if (x > MaxUsedKeySym) { 2818 MaxUsedKeySym = x; 2819 } 2820 } 2821 2822#if KMInit_dolog 2823 dbglog_writelnHex("MaxUsedKeySym", MaxUsedKeySym); 2824#endif 2825 2826 for (i = 0; i < 256; ++i) { 2827 KC2MKC[i] = MKC_None; 2828 } 2829 2830 XDisplayKeycodes(x_display, &first_keycode, &last_keycode); 2831 KeyMap = XGetKeyboardMapping(x_display, 2832 first_keycode, 2833 last_keycode - first_keycode + 1, 2834 &keysyms_per_keycode); 2835 2836 last_j = kNumMTs - 1; 2837 2838 for (i = first_keycode; i <= last_keycode; i++) { 2839 KeySym ks = KeyMap[(i - first_keycode) * keysyms_per_keycode]; 2840 2841#if KMInit_dolog 2842 dbglog_writeNum(i); 2843 dbglog_writeSpace(); 2844 dbglog_writeHex(ks); 2845 dbglog_writeSpace(); 2846#endif 2847 if (0 == ks) { 2848#if KMInit_dolog 2849 dbglog_writeCStr("zero"); 2850#endif 2851 } else 2852 if (ks > MaxUsedKeySym) { 2853#if KMInit_dolog 2854 dbglog_writeCStr("too large"); 2855#endif 2856 } else 2857 { 2858 /* 2859 look up in the translation table, and try to be more 2860 efficient if the order of this table is similar 2861 to the order of the X11 KeyboardMapping. 2862 */ 2863 j = last_j; 2864label_retry: 2865 ++j; 2866 if (j >= kNumMTs) { 2867 j = 0; 2868 } 2869 2870 if (j == last_j) { 2871 /* back where we started */ 2872#if KMInit_dolog 2873 dbglog_writeCStr("not found"); 2874#endif 2875 } else 2876 if (ks != MT2KeySym[j]) { 2877#if KMInit_dolog && 1 2878 dbglog_writeCStr("*"); 2879#endif 2880 goto label_retry; /* try the next one */ 2881 } else 2882 { 2883#if KMInit_dolog 2884 dbglog_writeCStr("match"); 2885 dbglog_writeSpace(); 2886 dbglog_writeHex(MT2MKC[j]); 2887#endif 2888 KC2MKC[i] = MT2MKC[j]; 2889 last_j = j; 2890 } 2891 } 2892#if KMInit_dolog 2893 dbglog_writeReturn(); 2894#endif 2895 } 2896 2897 XFree(KeyMap); 2898 2899 InitKeyCodes(); 2900 2901 return trueblnr; 2902} 2903 2904LOCALPROC CheckTheCapsLock(void) 2905{ 2906 int NewMousePosh; 2907 int NewMousePosv; 2908 int root_x_return; 2909 int root_y_return; 2910 Window root_return; 2911 Window child_return; 2912 unsigned int mask_return; 2913 2914 XQueryPointer(x_display, my_main_wind, 2915 &root_return, &child_return, 2916 &root_x_return, &root_y_return, 2917 &NewMousePosh, &NewMousePosv, 2918 &mask_return); 2919 2920 Keyboard_UpdateKeyMap2(MKC_formac_CapsLock, 2921 (mask_return & LockMask) != 0); 2922} 2923 2924LOCALPROC DoKeyCode0(int i, blnr down) 2925{ 2926 ui3r key = KC2MKC[i]; 2927 2928 if (MKC_None == key) { 2929 /* ignore */ 2930 } else 2931 if (MKC_real_CapsLock == key) { 2932 /* also ignore */ 2933 } else 2934 { 2935 Keyboard_UpdateKeyMap2(key, down); 2936 } 2937} 2938 2939LOCALPROC DoKeyCode(int i, blnr down) 2940{ 2941 if ((i >= 0) && (i < 256)) { 2942 ui3r key = KC2MKC[i]; 2943 2944 if (MKC_None == key) { 2945 /* ignore */ 2946 } else 2947 if (MKC_real_CapsLock == key) { 2948 CheckTheCapsLock(); 2949 } else 2950 { 2951 Keyboard_UpdateKeyMap2(key, down); 2952 } 2953 } 2954} 2955 2956#if MayFullScreen && GrabKeysFullScreen 2957LOCALVAR blnr KeyboardIsGrabbed = falseblnr; 2958#endif 2959 2960#if MayFullScreen && GrabKeysFullScreen 2961LOCALPROC MyGrabKeyboard(void) 2962{ 2963 if (! KeyboardIsGrabbed) { 2964 (void) XGrabKeyboard(x_display, my_main_wind, 2965 False, GrabModeAsync, GrabModeAsync, 2966 CurrentTime); 2967 KeyboardIsGrabbed = trueblnr; 2968 } 2969} 2970#endif 2971 2972#if MayFullScreen && GrabKeysFullScreen 2973LOCALPROC MyUnGrabKeyboard(void) 2974{ 2975 if (KeyboardIsGrabbed && my_main_wind) { 2976 XUngrabKeyboard(x_display, CurrentTime); 2977 KeyboardIsGrabbed = falseblnr; 2978 } 2979} 2980#endif 2981 2982LOCALVAR blnr NoKeyRepeat = falseblnr; 2983LOCALVAR int SaveKeyRepeat; 2984 2985LOCALPROC DisableKeyRepeat(void) 2986{ 2987 XKeyboardState r; 2988 XKeyboardControl k; 2989 2990 if ((! NoKeyRepeat) && (x_display != NULL)) { 2991 NoKeyRepeat = trueblnr; 2992 2993 XGetKeyboardControl(x_display, &r); 2994 SaveKeyRepeat = r.global_auto_repeat; 2995 2996 k.auto_repeat_mode = AutoRepeatModeOff; 2997 XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k); 2998 } 2999} 3000 3001LOCALPROC RestoreKeyRepeat(void) 3002{ 3003 XKeyboardControl k; 3004 3005 if (NoKeyRepeat && (x_display != NULL)) { 3006 NoKeyRepeat = falseblnr; 3007 3008 k.auto_repeat_mode = SaveKeyRepeat; 3009 XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k); 3010 } 3011} 3012 3013LOCALVAR blnr WantCmdOptOnReconnect = falseblnr; 3014 3015LOCALPROC GetTheDownKeys(void) 3016{ 3017 char keys_return[32]; 3018 int i; 3019 int v; 3020 int j; 3021 3022 XQueryKeymap(x_display, keys_return); 3023 3024 for (i = 0; i < 32; ++i) { 3025 v = keys_return[i]; 3026 for (j = 0; j < 8; ++j) { 3027 if (0 != ((1 << j) & v)) { 3028 int k = i * 8 + j; 3029 3030 DoKeyCode0(k, trueblnr); 3031 } 3032 } 3033 } 3034} 3035 3036LOCALPROC ReconnectKeyCodes3(void) 3037{ 3038 CheckTheCapsLock(); 3039 3040 if (WantCmdOptOnReconnect) { 3041 WantCmdOptOnReconnect = falseblnr; 3042 3043 GetTheDownKeys(); 3044 } 3045} 3046 3047LOCALPROC DisconnectKeyCodes3(void) 3048{ 3049 DisconnectKeyCodes2(); 3050 MyMouseButtonSet(falseblnr); 3051} 3052 3053/* --- time, date, location --- */ 3054 3055#define dbglog_TimeStuff (0 && dbglog_HAVE) 3056 3057LOCALVAR ui5b TrueEmulatedTime = 0; 3058 3059#include "DATE2SEC.h" 3060 3061#define TicksPerSecond 1000000 3062 3063LOCALVAR blnr HaveTimeDelta = falseblnr; 3064LOCALVAR ui5b TimeDelta; 3065 3066LOCALVAR ui5b NewMacDateInSeconds; 3067 3068LOCALVAR ui5b LastTimeSec; 3069LOCALVAR ui5b LastTimeUsec; 3070 3071LOCALPROC GetCurrentTicks(void) 3072{ 3073 struct timeval t; 3074 3075 gettimeofday(&t, NULL); 3076 if (! HaveTimeDelta) { 3077 time_t Current_Time; 3078 struct tm *s; 3079 3080 (void) time(&Current_Time); 3081 s = localtime(&Current_Time); 3082 TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour, 3083 s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec; 3084#if 0 && AutoTimeZone /* how portable is this ? */ 3085 CurMacDelta = ((ui5b)(s->tm_gmtoff) & 0x00FFFFFF) 3086 | ((s->tm_isdst ? 0x80 : 0) << 24); 3087#endif 3088 HaveTimeDelta = trueblnr; 3089 } 3090 3091 NewMacDateInSeconds = t.tv_sec + TimeDelta; 3092 LastTimeSec = (ui5b)t.tv_sec; 3093 LastTimeUsec = (ui5b)t.tv_usec; 3094} 3095 3096#define MyInvTimeStep 16626 /* TicksPerSecond / 60.14742 */ 3097 3098LOCALVAR ui5b NextTimeSec; 3099LOCALVAR ui5b NextTimeUsec; 3100 3101LOCALPROC IncrNextTime(void) 3102{ 3103 NextTimeUsec += MyInvTimeStep; 3104 if (NextTimeUsec >= TicksPerSecond) { 3105 NextTimeUsec -= TicksPerSecond; 3106 NextTimeSec += 1; 3107 } 3108} 3109 3110LOCALPROC InitNextTime(void) 3111{ 3112 NextTimeSec = LastTimeSec; 3113 NextTimeUsec = LastTimeUsec; 3114 IncrNextTime(); 3115} 3116 3117LOCALPROC StartUpTimeAdjust(void) 3118{ 3119 GetCurrentTicks(); 3120 InitNextTime(); 3121} 3122 3123LOCALFUNC si5b GetTimeDiff(void) 3124{ 3125 return ((si5b)(LastTimeSec - NextTimeSec)) * TicksPerSecond 3126 + ((si5b)(LastTimeUsec - NextTimeUsec)); 3127} 3128 3129LOCALPROC UpdateTrueEmulatedTime(void) 3130{ 3131 si5b TimeDiff; 3132 3133 GetCurrentTicks(); 3134 3135 TimeDiff = GetTimeDiff(); 3136 if (TimeDiff >= 0) { 3137 if (TimeDiff > 16 * MyInvTimeStep) { 3138 /* emulation interrupted, forget it */ 3139 ++TrueEmulatedTime; 3140 InitNextTime(); 3141 3142#if dbglog_TimeStuff 3143 dbglog_writelnNum("emulation interrupted", 3144 TrueEmulatedTime); 3145#endif 3146 } else { 3147 do { 3148 ++TrueEmulatedTime; 3149 IncrNextTime(); 3150 TimeDiff -= TicksPerSecond; 3151 } while (TimeDiff >= 0); 3152 } 3153 } else if (TimeDiff < - 16 * MyInvTimeStep) { 3154 /* clock goofed if ever get here, reset */ 3155#if dbglog_TimeStuff 3156 dbglog_writeln("clock set back"); 3157#endif 3158 3159 InitNextTime(); 3160 } 3161} 3162 3163LOCALFUNC blnr CheckDateTime(void) 3164{ 3165 if (CurMacDateInSeconds != NewMacDateInSeconds) { 3166 CurMacDateInSeconds = NewMacDateInSeconds; 3167 return trueblnr; 3168 } else { 3169 return falseblnr; 3170 } 3171} 3172 3173LOCALFUNC blnr InitLocationDat(void) 3174{ 3175 GetCurrentTicks(); 3176 CurMacDateInSeconds = NewMacDateInSeconds; 3177 3178 return trueblnr; 3179} 3180 3181/* --- sound --- */ 3182 3183#if MySoundEnabled 3184 3185#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */ 3186#define kSoundBuffers (1 << kLn2SoundBuffers) 3187#define kSoundBuffMask (kSoundBuffers - 1) 3188 3189#define DesiredMinFilledSoundBuffs 3 3190 /* 3191 if too big then sound lags behind emulation. 3192 if too small then sound will have pauses. 3193 */ 3194 3195#define kLnOneBuffLen 9 3196#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen) 3197#define kOneBuffLen (1UL << kLnOneBuffLen) 3198#define kAllBuffLen (1UL << kLnAllBuffLen) 3199#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3) 3200#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3) 3201#define kOneBuffSz (1UL << kLnOneBuffSz) 3202#define kAllBuffSz (1UL << kLnAllBuffSz) 3203#define kOneBuffMask (kOneBuffLen - 1) 3204#define kAllBuffMask (kAllBuffLen - 1) 3205#define dbhBufferSize (kAllBuffSz + kOneBuffSz) 3206 3207#define dbglog_SoundStuff (0 && dbglog_HAVE) 3208#define dbglog_SoundBuffStats (0 && dbglog_HAVE) 3209 3210LOCALVAR tpSoundSamp TheSoundBuffer = nullpr; 3211LOCALVAR ui4b ThePlayOffset; 3212LOCALVAR ui4b TheFillOffset; 3213LOCALVAR ui4b TheWriteOffset; 3214LOCALVAR ui4b MinFilledSoundBuffs; 3215 3216LOCALPROC MySound_Start0(void) 3217{ 3218 /* Reset variables */ 3219 ThePlayOffset = 0; 3220 TheFillOffset = 0; 3221 TheWriteOffset = 0; 3222 MinFilledSoundBuffs = kSoundBuffers; 3223} 3224 3225GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL) 3226{ 3227 ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset); 3228 ui4b WriteBuffContig = 3229 kOneBuffLen - (TheWriteOffset & kOneBuffMask); 3230 3231 if (WriteBuffContig < n) { 3232 n = WriteBuffContig; 3233 } 3234 if (ToFillLen < n) { 3235 /* overwrite previous buffer */ 3236#if dbglog_SoundStuff 3237 dbglog_writeln("sound buffer over flow"); 3238#endif 3239 TheWriteOffset -= kOneBuffLen; 3240 } 3241 3242 *actL = n; 3243 return TheSoundBuffer + (TheWriteOffset & kAllBuffMask); 3244} 3245 3246LOCALFUNC blnr MySound_EndWrite0(ui4r actL) 3247{ 3248 blnr v; 3249 3250 TheWriteOffset += actL; 3251 3252 if (0 != (TheWriteOffset & kOneBuffMask)) { 3253 v = falseblnr; 3254 } else { 3255 /* just finished a block */ 3256 3257 TheFillOffset = TheWriteOffset; 3258 3259 v = trueblnr; 3260 } 3261 3262 return v; 3263} 3264 3265LOCALPROC MySound_SecondNotify0(void) 3266{ 3267 if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) { 3268#if dbglog_SoundStuff 3269 dbglog_writeln("MinFilledSoundBuffs too high"); 3270#endif 3271 IncrNextTime(); 3272 } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) { 3273#if dbglog_SoundStuff 3274 dbglog_writeln("MinFilledSoundBuffs too low"); 3275#endif 3276 ++TrueEmulatedTime; 3277 } 3278 MinFilledSoundBuffs = kSoundBuffers; 3279} 3280 3281#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */ 3282 3283#include "SOUNDGLU.h" 3284 3285#endif 3286 3287/* --- basic dialogs --- */ 3288 3289LOCALPROC CheckSavedMacMsg(void) 3290{ 3291 if (nullpr != SavedBriefMsg) { 3292 char briefMsg0[ClStrMaxLength + 1]; 3293 char longMsg0[ClStrMaxLength + 1]; 3294 3295 NativeStrFromCStr(briefMsg0, SavedBriefMsg); 3296 NativeStrFromCStr(longMsg0, SavedLongMsg); 3297 3298 fprintf(stderr, "%s\n", briefMsg0); 3299 fprintf(stderr, "%s\n", longMsg0); 3300 3301 SavedBriefMsg = nullpr; 3302 } 3303} 3304 3305/* --- clipboard --- */ 3306 3307#if IncludeHostTextClipExchange 3308LOCALVAR ui3p MyClipBuffer = NULL; 3309#endif 3310 3311#if IncludeHostTextClipExchange 3312LOCALPROC FreeMyClipBuffer(void) 3313{ 3314 if (MyClipBuffer != NULL) { 3315 free(MyClipBuffer); 3316 MyClipBuffer = NULL; 3317 } 3318} 3319#endif 3320 3321#if IncludeHostTextClipExchange 3322GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i) 3323{ 3324 tMacErr err = mnvm_miscErr; 3325 3326 FreeMyClipBuffer(); 3327 if (MacRomanTextToNativePtr(i, falseblnr, 3328 &MyClipBuffer)) 3329 { 3330 XSetSelectionOwner(x_display, MyXA_CLIPBOARD, 3331 my_main_wind, CurrentTime); 3332 err = mnvm_noErr; 3333 } 3334 3335 PbufDispose(i); 3336 3337 return err; 3338} 3339#endif 3340 3341#if IncludeHostTextClipExchange 3342LOCALFUNC blnr WaitForClipboardSelection(XEvent *xevent) 3343{ 3344 struct timespec rqt; 3345 struct timespec rmt; 3346 int i; 3347 3348 for (i = 100; --i >= 0; ) { 3349 while (XCheckTypedWindowEvent(x_display, my_main_wind, 3350 SelectionNotify, xevent)) 3351 { 3352 if (xevent->xselection.selection != MyXA_CLIPBOARD) { 3353 /* 3354 not what we were looking for. lose it. 3355 (and hope it wasn't too important). 3356 */ 3357 WriteExtraErr("Discarding unwanted SelectionNotify"); 3358 } else { 3359 /* this is our event */ 3360 return trueblnr; 3361 } 3362 } 3363 3364 rqt.tv_sec = 0; 3365 rqt.tv_nsec = 10000000; 3366 (void) nanosleep(&rqt, &rmt); 3367 } 3368 return falseblnr; 3369} 3370#endif 3371 3372#if IncludeHostTextClipExchange 3373LOCALPROC HTCEimport_do(void) 3374{ 3375 Window w = XGetSelectionOwner(x_display, MyXA_CLIPBOARD); 3376 3377 if (w == my_main_wind) { 3378 /* We own the clipboard, already have MyClipBuffer */ 3379 } else { 3380 FreeMyClipBuffer(); 3381 if (w != None) { 3382 XEvent xevent; 3383 3384 XDeleteProperty(x_display, my_main_wind, 3385 MyXA_MinivMac_Clip); 3386 XConvertSelection(x_display, MyXA_CLIPBOARD, XA_STRING, 3387 MyXA_MinivMac_Clip, my_main_wind, CurrentTime); 3388 3389 if (WaitForClipboardSelection(&xevent)) { 3390 if (None == xevent.xselection.property) { 3391 /* oops, target not supported */ 3392 } else { 3393 if (xevent.xselection.property 3394 != MyXA_MinivMac_Clip) 3395 { 3396 /* not where we expected it */ 3397 } else { 3398 Atom ret_type; 3399 int ret_format; 3400 unsigned long ret_item; 3401 unsigned long remain_byte; 3402 unsigned char *s = NULL; 3403 3404 if ((Success != XGetWindowProperty( 3405 x_display, my_main_wind, MyXA_MinivMac_Clip, 3406 0, 65535, False, AnyPropertyType, &ret_type, 3407 &ret_format, &ret_item, &remain_byte, &s)) 3408 || (ret_type != XA_STRING) 3409 || (ret_format != 8) 3410 || (NULL == s)) 3411 { 3412 WriteExtraErr( 3413 "XGetWindowProperty failed" 3414 " in HTCEimport_do"); 3415 } else { 3416 MyClipBuffer = (ui3p)malloc(ret_item + 1); 3417 if (NULL == MyClipBuffer) { 3418 MacMsg(kStrOutOfMemTitle, 3419 kStrOutOfMemMessage, falseblnr); 3420 } else { 3421 MyMoveBytes((anyp)s, (anyp)MyClipBuffer, 3422 ret_item); 3423 MyClipBuffer[ret_item] = 0; 3424 } 3425 XFree(s); 3426 } 3427 } 3428 XDeleteProperty(x_display, my_main_wind, 3429 MyXA_MinivMac_Clip); 3430 } 3431 } 3432 } 3433 } 3434} 3435#endif 3436 3437#if IncludeHostTextClipExchange 3438GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r) 3439{ 3440 HTCEimport_do(); 3441 3442 return NativeTextToMacRomanPbuf((char *)MyClipBuffer, r); 3443} 3444#endif 3445 3446#if IncludeHostTextClipExchange 3447LOCALFUNC blnr HandleSelectionRequestClipboard(XEvent *theEvent) 3448{ 3449 blnr RequestFilled = falseblnr; 3450 3451#if MyDbgEvents 3452 dbglog_writeln("Requested MyXA_CLIPBOARD"); 3453#endif 3454 3455 if (NULL == MyClipBuffer) { 3456 /* our clipboard is empty */ 3457 } else if (theEvent->xselectionrequest.target == MyXA_TARGETS) { 3458 Atom a[2]; 3459 3460 a[0] = MyXA_TARGETS; 3461 a[1] = XA_STRING; 3462 3463 XChangeProperty(x_display, 3464 theEvent->xselectionrequest.requestor, 3465 theEvent->xselectionrequest.property, 3466 MyXA_TARGETS, 3467 32, 3468 /* 3469 most, but not all, other programs I've 3470 look at seem to use 8 here, but that 3471 can't be right. can it? 3472 */ 3473 PropModeReplace, 3474 (unsigned char *)a, 3475 sizeof(a) / sizeof(Atom)); 3476 3477 RequestFilled = trueblnr; 3478 } else if (theEvent->xselectionrequest.target == XA_STRING) { 3479 XChangeProperty(x_display, 3480 theEvent->xselectionrequest.requestor, 3481 theEvent->xselectionrequest.property, 3482 XA_STRING, 3483 8, 3484 PropModeReplace, 3485 (unsigned char *)MyClipBuffer, 3486 strlen((char *)MyClipBuffer)); 3487 3488 RequestFilled = trueblnr; 3489 } 3490 3491 return RequestFilled; 3492} 3493#endif 3494 3495/* --- drag and drop --- */ 3496 3497#if EnableDragDrop 3498LOCALPROC MyActivateWind(Time time) 3499{ 3500 if (NetSupportedContains(MyXA_NetActiveWindow)) { 3501 XEvent xevent; 3502 Window rootwin = XRootWindow(x_display, 3503 DefaultScreen(x_display)); 3504 3505 memset(&xevent, 0, sizeof (xevent)); 3506 3507 xevent.xany.type = ClientMessage; 3508 xevent.xclient.send_event = True; 3509 xevent.xclient.window = my_main_wind; 3510 xevent.xclient.message_type = MyXA_NetActiveWindow; 3511 xevent.xclient.format = 32; 3512 xevent.xclient.data.l[0] = 1; 3513 xevent.xclient.data.l[1]= time; 3514 3515 if (0 == XSendEvent(x_display, rootwin, 0, 3516 SubstructureRedirectMask | SubstructureNotifyMask, 3517 &xevent)) 3518 { 3519 WriteExtraErr("XSendEvent failed in MyActivateWind"); 3520 } 3521 } 3522 3523 XRaiseWindow(x_display, my_main_wind); 3524 /* 3525 In RedHat 7.1, _NET_ACTIVE_WINDOW supported, 3526 but XSendEvent of _NET_ACTIVE_WINDOW 3527 doesn't raise the window. So just always 3528 call XRaiseWindow. Hopefully calling 3529 XRaiseWindow won't do any harm on window 3530 managers where it isn't needed. 3531 (Such as in Ubuntu 5.10) 3532 */ 3533 XSetInputFocus(x_display, my_main_wind, 3534 RevertToPointerRoot, time); 3535 /* And call this always too, just in case */ 3536} 3537#endif 3538 3539#if EnableDragDrop 3540LOCALPROC ParseOneUri(char *s) 3541{ 3542 /* printf("ParseOneUri %s\n", s); */ 3543 if (('f' == s[0]) && ('i' == s[1]) && ('l' == s[2]) 3544 && ('e' == s[3]) && (':' == s[4])) 3545 { 3546 s += 5; 3547 if (('/' == s[0]) && ('/' == s[1])) { 3548 /* skip hostname */ 3549 char c; 3550 3551 s += 2; 3552 while ((c = *s) != '/') { 3553 if (0 == c) { 3554 return; 3555 } 3556 ++s; 3557 } 3558 } 3559 (void) Sony_Insert1a(s, falseblnr); 3560 } 3561} 3562#endif 3563 3564#if EnableDragDrop 3565LOCALFUNC int HexChar2Nib(char x) 3566{ 3567 if ((x >= '0') && (x <= '9')) { 3568 return x - '0'; 3569 } else if ((x >= 'A') && (x <= 'F')) { 3570 return x - 'A' + 10; 3571 } else if ((x >= 'a') && (x <= 'f')) { 3572 return x - 'a' + 10; 3573 } else { 3574 return -1; 3575 } 3576} 3577#endif 3578 3579#if EnableDragDrop 3580LOCALPROC ParseUriList(char *s) 3581{ 3582 char *p1 = s; 3583 char *p0 = s; 3584 char *p = s; 3585 char c; 3586 3587 /* printf("ParseUriList %s\n", s); */ 3588 while ((c = *p++) != 0) { 3589 if ('%' == c) { 3590 int a; 3591 int b; 3592 3593 if (((a = HexChar2Nib(p[0])) >= 0) && 3594 ((b = HexChar2Nib(p[1])) >= 0)) 3595 { 3596 p += 2; 3597 *p1++ = (a << 4) + b; 3598 } else { 3599 *p1++ = c; 3600 } 3601 } else if (('\n' == c) || ('\r' == c)) { 3602 *p1++ = 0; 3603 ParseOneUri(p0); 3604 p0 = p1; 3605 } else { 3606 *p1++ = c; 3607 } 3608 } 3609 *p1++ = 0; 3610 ParseOneUri(p0); 3611} 3612#endif 3613 3614#if EnableDragDrop 3615LOCALVAR Window PendingDragWindow = None; 3616#endif 3617 3618#if EnableDragDrop 3619LOCALPROC HandleSelectionNotifyDnd(XEvent *theEvent) 3620{ 3621 blnr DropOk = falseblnr; 3622 3623#if MyDbgEvents 3624 dbglog_writeln("Got MyXA_DndSelection"); 3625#endif 3626 3627 if ((theEvent->xselection.property == MyXA_MinivMac_DndXchng) 3628 && (theEvent->xselection.target == MyXA_UriList)) 3629 { 3630 Atom ret_type; 3631 int ret_format; 3632 unsigned long ret_item; 3633 unsigned long remain_byte; 3634 unsigned char *s = NULL; 3635 3636 if ((Success != XGetWindowProperty(x_display, my_main_wind, 3637 MyXA_MinivMac_DndXchng, 3638 0, 65535, False, MyXA_UriList, &ret_type, &ret_format, 3639 &ret_item, &remain_byte, &s)) 3640 || (NULL == s)) 3641 { 3642 WriteExtraErr( 3643 "XGetWindowProperty failed in SelectionNotify"); 3644 } else { 3645 ParseUriList((char *)s); 3646 DropOk = trueblnr; 3647 XFree(s); 3648 } 3649 } else { 3650 WriteExtraErr("Got Unknown SelectionNotify"); 3651 } 3652 3653 XDeleteProperty(x_display, my_main_wind, 3654 MyXA_MinivMac_DndXchng); 3655 3656 if (PendingDragWindow != None) { 3657 XEvent xevent; 3658 3659 memset(&xevent, 0, sizeof(xevent)); 3660 3661 xevent.xany.type = ClientMessage; 3662 xevent.xany.display = x_display; 3663 xevent.xclient.window = PendingDragWindow; 3664 xevent.xclient.message_type = MyXA_DndFinished; 3665 xevent.xclient.format = 32; 3666 3667 xevent.xclient.data.l[0] = my_main_wind; 3668 if (DropOk) { 3669 xevent.xclient.data.l[1] = 1; 3670 } 3671 xevent.xclient.data.l[2] = MyXA_DndActionPrivate; 3672 3673 if (0 == XSendEvent(x_display, 3674 PendingDragWindow, 0, 0, &xevent)) 3675 { 3676 WriteExtraErr("XSendEvent failed in SelectionNotify"); 3677 } 3678 } 3679 if (DropOk && gTrueBackgroundFlag) { 3680 MyActivateWind(theEvent->xselection.time); 3681 3682 WantCmdOptOnReconnect = trueblnr; 3683 } 3684} 3685#endif 3686 3687#if EnableDragDrop 3688LOCALPROC HandleClientMessageDndPosition(XEvent *theEvent) 3689{ 3690 XEvent xevent; 3691 int xr; 3692 int yr; 3693 unsigned int dr; 3694 unsigned int wr; 3695 unsigned int hr; 3696 unsigned int bwr; 3697 Window rr; 3698 Window srcwin = theEvent->xclient.data.l[0]; 3699 3700#if MyDbgEvents 3701 dbglog_writeln("Got XdndPosition"); 3702#endif 3703 3704 XGetGeometry(x_display, my_main_wind, 3705 &rr, &xr, &yr, &wr, &hr, &bwr, &dr); 3706 memset (&xevent, 0, sizeof(xevent)); 3707 xevent.xany.type = ClientMessage; 3708 xevent.xany.display = x_display; 3709 xevent.xclient.window = srcwin; 3710 xevent.xclient.message_type = MyXA_DndStatus; 3711 xevent.xclient.format = 32; 3712 3713 xevent.xclient.data.l[0] = theEvent->xclient.window; 3714 /* Target Window */ 3715 xevent.xclient.data.l[1] = 1; /* Accept */ 3716 xevent.xclient.data.l[2] = ((xr) << 16) | ((yr) & 0xFFFFUL); 3717 xevent.xclient.data.l[3] = ((wr) << 16) | ((hr) & 0xFFFFUL); 3718 xevent.xclient.data.l[4] = MyXA_DndActionPrivate; /* Action */ 3719 3720 if (0 == XSendEvent(x_display, srcwin, 0, 0, &xevent)) { 3721 WriteExtraErr( 3722 "XSendEvent failed in HandleClientMessageDndPosition"); 3723 } 3724} 3725#endif 3726 3727#if EnableDragDrop 3728LOCALPROC HandleClientMessageDndDrop(XEvent *theEvent) 3729{ 3730 Time timestamp = theEvent->xclient.data.l[2]; 3731 PendingDragWindow = (Window) theEvent->xclient.data.l[0]; 3732 3733#if MyDbgEvents 3734 dbglog_writeln("Got XdndDrop"); 3735#endif 3736 3737 XConvertSelection(x_display, MyXA_DndSelection, MyXA_UriList, 3738 MyXA_MinivMac_DndXchng, my_main_wind, timestamp); 3739} 3740#endif 3741 3742 3743#if EmLocalTalk 3744 3745struct xqpr { 3746 int NewMousePosh; 3747 int NewMousePosv; 3748 int root_x_return; 3749 int root_y_return; 3750 Window root_return; 3751 Window child_return; 3752 unsigned int mask_return; 3753}; 3754typedef struct xqpr xqpr; 3755 3756 3757LOCALFUNC blnr EntropyGather(void) 3758{ 3759 /* 3760 gather some entropy from several places, just in case 3761 /dev/urandom is not available. 3762 */ 3763 3764 { 3765 struct timeval t; 3766 3767 gettimeofday(&t, NULL); 3768 3769 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b)); 3770 } 3771 3772 { 3773 xqpr t; 3774 3775 XQueryPointer(x_display, my_main_wind, 3776 &t.root_return, &t.child_return, 3777 &t.root_x_return, &t.root_y_return, 3778 &t.NewMousePosh, &t.NewMousePosv, 3779 &t.mask_return); 3780 3781 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b)); 3782 } 3783 3784#if 0 3785 /* 3786 Another possible source of entropy. But if available, 3787 almost certainly /dev/urandom is also available. 3788 */ 3789 /* #include <sys/sysinfo.h> */ 3790 { 3791 struct sysinfo t; 3792 3793 if (0 != sysinfo(&t)) { 3794#if dbglog_HAVE 3795 dbglog_writeln("sysinfo fails"); 3796#endif 3797 } 3798 3799 /* 3800 continue even if error, it doesn't hurt anything 3801 if t is garbage. 3802 */ 3803 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b)); 3804 } 3805#endif 3806 3807 { 3808 pid_t t = getpid(); 3809 3810 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b)); 3811 } 3812 3813 { 3814 ui5b dat[2]; 3815 int fd; 3816 3817 if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { 3818#if dbglog_HAVE 3819 dbglog_writeCStr("open /dev/urandom fails"); 3820 dbglog_writeNum(errno); 3821 dbglog_writeCStr(" ("); 3822 dbglog_writeCStr(strerror(errno)); 3823 dbglog_writeCStr(")"); 3824 dbglog_writeReturn(); 3825#endif 3826 } else { 3827 3828 if (read(fd, &dat, sizeof(dat)) < 0) { 3829#if dbglog_HAVE 3830 dbglog_writeCStr("open /dev/urandom fails"); 3831 dbglog_writeNum(errno); 3832 dbglog_writeCStr(" ("); 3833 dbglog_writeCStr(strerror(errno)); 3834 dbglog_writeCStr(")"); 3835 dbglog_writeReturn(); 3836#endif 3837 } else { 3838 3839#if dbglog_HAVE 3840 dbglog_writeCStr("dat: "); 3841 dbglog_writeHex(dat[0]); 3842 dbglog_writeCStr(" "); 3843 dbglog_writeHex(dat[1]); 3844 dbglog_writeReturn(); 3845#endif 3846 3847 e_p[0] ^= dat[0]; 3848 e_p[1] ^= dat[1]; 3849 /* 3850 if "/dev/urandom" is working correctly, 3851 this should make the previous contents of e_p 3852 irrelevant. if it is completely broken, like 3853 returning 0, this will not make e_p any less 3854 random. 3855 */ 3856 3857#if dbglog_HAVE 3858 dbglog_writeCStr("ep: "); 3859 dbglog_writeHex(e_p[0]); 3860 dbglog_writeCStr(" "); 3861 dbglog_writeHex(e_p[1]); 3862 dbglog_writeReturn(); 3863#endif 3864 } 3865 3866 close(fd); 3867 } 3868 } 3869 3870 return trueblnr; 3871} 3872#endif 3873 3874#if EmLocalTalk 3875 3876#include "LOCALTLK.h" 3877 3878#endif 3879 3880 3881#define UseMotionEvents 1 3882 3883#if UseMotionEvents 3884LOCALVAR blnr CaughtMouse = falseblnr; 3885#endif 3886 3887#if MayNotFullScreen 3888LOCALVAR int SavedTransH; 3889LOCALVAR int SavedTransV; 3890#endif 3891 3892/* --- event handling for main window --- */ 3893 3894LOCALPROC HandleTheEvent(XEvent *theEvent) 3895{ 3896 if (theEvent->xany.display != x_display) { 3897 WriteExtraErr("Got event for some other display"); 3898 } else switch(theEvent->type) { 3899 case KeyPress: 3900 if (theEvent->xkey.window != my_main_wind) { 3901 WriteExtraErr("Got KeyPress for some other window"); 3902 } else { 3903#if MyDbgEvents 3904 dbglog_writeln("- event - KeyPress"); 3905#endif 3906 3907 MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y); 3908 DoKeyCode(theEvent->xkey.keycode, trueblnr); 3909 } 3910 break; 3911 case KeyRelease: 3912 if (theEvent->xkey.window != my_main_wind) { 3913 WriteExtraErr("Got KeyRelease for some other window"); 3914 } else { 3915#if MyDbgEvents 3916 dbglog_writeln("- event - KeyRelease"); 3917#endif 3918 3919 MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y); 3920 DoKeyCode(theEvent->xkey.keycode, falseblnr); 3921 } 3922 break; 3923 case ButtonPress: 3924 /* any mouse button, we don't care which */ 3925 if (theEvent->xbutton.window != my_main_wind) { 3926 WriteExtraErr("Got ButtonPress for some other window"); 3927 } else { 3928 /* 3929 could check some modifiers, but don't bother for now 3930 Keyboard_UpdateKeyMap2(MKC_formac_CapsLock, 3931 (theEvent->xbutton.state & LockMask) != 0); 3932 */ 3933 MousePositionNotify( 3934 theEvent->xbutton.x, theEvent->xbutton.y); 3935 MyMouseButtonSet(trueblnr); 3936 } 3937 break; 3938 case ButtonRelease: 3939 /* any mouse button, we don't care which */ 3940 if (theEvent->xbutton.window != my_main_wind) { 3941 WriteExtraErr( 3942 "Got ButtonRelease for some other window"); 3943 } else { 3944 MousePositionNotify( 3945 theEvent->xbutton.x, theEvent->xbutton.y); 3946 MyMouseButtonSet(falseblnr); 3947 } 3948 break; 3949#if UseMotionEvents 3950 case MotionNotify: 3951 if (theEvent->xmotion.window != my_main_wind) { 3952 WriteExtraErr("Got MotionNotify for some other window"); 3953 } else { 3954 MousePositionNotify( 3955 theEvent->xmotion.x, theEvent->xmotion.y); 3956 } 3957 break; 3958 case EnterNotify: 3959 if (theEvent->xcrossing.window != my_main_wind) { 3960 WriteExtraErr("Got EnterNotify for some other window"); 3961 } else { 3962#if MyDbgEvents 3963 dbglog_writeln("- event - EnterNotify"); 3964#endif 3965 3966 CaughtMouse = trueblnr; 3967 MousePositionNotify( 3968 theEvent->xcrossing.x, theEvent->xcrossing.y); 3969 } 3970 break; 3971 case LeaveNotify: 3972 if (theEvent->xcrossing.window != my_main_wind) { 3973 WriteExtraErr("Got LeaveNotify for some other window"); 3974 } else { 3975#if MyDbgEvents 3976 dbglog_writeln("- event - LeaveNotify"); 3977#endif 3978 3979 MousePositionNotify( 3980 theEvent->xcrossing.x, theEvent->xcrossing.y); 3981 CaughtMouse = falseblnr; 3982 } 3983 break; 3984#endif 3985 case Expose: 3986 if (theEvent->xexpose.window != my_main_wind) { 3987 WriteExtraErr( 3988 "Got SelectionRequest for some other window"); 3989 } else { 3990 int x0 = theEvent->xexpose.x; 3991 int y0 = theEvent->xexpose.y; 3992 int x1 = x0 + theEvent->xexpose.width; 3993 int y1 = y0 + theEvent->xexpose.height; 3994 3995#if 0 && MyDbgEvents 3996 dbglog_writeln("- event - Expose"); 3997#endif 3998 3999#if VarFullScreen 4000 if (UseFullScreen) 4001#endif 4002#if MayFullScreen 4003 { 4004 x0 -= hOffset; 4005 y0 -= vOffset; 4006 x1 -= hOffset; 4007 y1 -= vOffset; 4008 } 4009#endif 4010 4011#if EnableMagnify 4012 if (UseMagnify) { 4013 x0 /= MyWindowScale; 4014 y0 /= MyWindowScale; 4015 x1 = (x1 + (MyWindowScale - 1)) / MyWindowScale; 4016 y1 = (y1 + (MyWindowScale - 1)) / MyWindowScale; 4017 } 4018#endif 4019 4020#if VarFullScreen 4021 if (UseFullScreen) 4022#endif 4023#if MayFullScreen 4024 { 4025 x0 += ViewHStart; 4026 y0 += ViewVStart; 4027 x1 += ViewHStart; 4028 y1 += ViewVStart; 4029 } 4030#endif 4031 4032 if (x0 < 0) { 4033 x0 = 0; 4034 } 4035 if (x1 > vMacScreenWidth) { 4036 x1 = vMacScreenWidth; 4037 } 4038 if (y0 < 0) { 4039 y0 = 0; 4040 } 4041 if (y1 > vMacScreenHeight) { 4042 y1 = vMacScreenHeight; 4043 } 4044 if ((x0 < x1) && (y0 < y1)) { 4045 HaveChangedScreenBuff(y0, x0, y1, x1); 4046 } 4047 4048 NeedFinishOpen1 = falseblnr; 4049 } 4050 break; 4051#if IncludeHostTextClipExchange 4052 case SelectionRequest: 4053 if (theEvent->xselectionrequest.owner != my_main_wind) { 4054 WriteExtraErr( 4055 "Got SelectionRequest for some other window"); 4056 } else { 4057 XEvent xevent; 4058 blnr RequestFilled = falseblnr; 4059 4060#if MyDbgEvents 4061 dbglog_writeln("- event - SelectionRequest"); 4062 WriteDbgAtom("selection", 4063 theEvent->xselectionrequest.selection); 4064 WriteDbgAtom("target", 4065 theEvent->xselectionrequest.target); 4066 WriteDbgAtom("property", 4067 theEvent->xselectionrequest.property); 4068#endif 4069 4070 if (theEvent->xselectionrequest.selection == 4071 MyXA_CLIPBOARD) 4072 { 4073 RequestFilled = 4074 HandleSelectionRequestClipboard(theEvent); 4075 } 4076 4077 4078 memset(&xevent, 0, sizeof(xevent)); 4079 xevent.xselection.type = SelectionNotify; 4080 xevent.xselection.display = x_display; 4081 xevent.xselection.requestor = 4082 theEvent->xselectionrequest.requestor; 4083 xevent.xselection.selection = 4084 theEvent->xselectionrequest.selection; 4085 xevent.xselection.target = 4086 theEvent->xselectionrequest.target; 4087 xevent.xselection.property = (! RequestFilled) ? None 4088 : theEvent->xselectionrequest.property ; 4089 xevent.xselection.time = 4090 theEvent->xselectionrequest.time; 4091 4092 if (0 == XSendEvent(x_display, 4093 xevent.xselection.requestor, False, 0, &xevent)) 4094 { 4095 WriteExtraErr( 4096 "XSendEvent failed in SelectionRequest"); 4097 } 4098 } 4099 break; 4100 case SelectionClear: 4101 if (theEvent->xselectionclear.window != my_main_wind) { 4102 WriteExtraErr( 4103 "Got SelectionClear for some other window"); 4104 } else { 4105#if MyDbgEvents 4106 dbglog_writeln("- event - SelectionClear"); 4107 WriteDbgAtom("selection", 4108 theEvent->xselectionclear.selection); 4109#endif 4110 4111 if (theEvent->xselectionclear.selection == 4112 MyXA_CLIPBOARD) 4113 { 4114 FreeMyClipBuffer(); 4115 } 4116 } 4117 break; 4118#endif 4119#if EnableDragDrop 4120 case SelectionNotify: 4121 if (theEvent->xselection.requestor != my_main_wind) { 4122 WriteExtraErr( 4123 "Got SelectionNotify for some other window"); 4124 } else { 4125#if MyDbgEvents 4126 dbglog_writeln("- event - SelectionNotify"); 4127 WriteDbgAtom("selection", 4128 theEvent->xselection.selection); 4129 WriteDbgAtom("target", theEvent->xselection.target); 4130 WriteDbgAtom("property", theEvent->xselection.property); 4131#endif 4132 4133 if (theEvent->xselection.selection == MyXA_DndSelection) 4134 { 4135 HandleSelectionNotifyDnd(theEvent); 4136 } else { 4137 WriteExtraErr( 4138 "Got Unknown selection in SelectionNotify"); 4139 } 4140 } 4141 break; 4142#endif 4143 case ClientMessage: 4144 if (theEvent->xclient.window != my_main_wind) { 4145 WriteExtraErr( 4146 "Got ClientMessage for some other window"); 4147 } else { 4148#if MyDbgEvents 4149 dbglog_writeln("- event - ClientMessage"); 4150 WriteDbgAtom("message_type", 4151 theEvent->xclient.message_type); 4152#endif 4153 4154#if EnableDragDrop 4155 if (theEvent->xclient.message_type == MyXA_DndEnter) { 4156 /* printf("Got XdndEnter\n"); */ 4157 } else if (theEvent->xclient.message_type == 4158 MyXA_DndLeave) 4159 { 4160 /* printf("Got XdndLeave\n"); */ 4161 } else if (theEvent->xclient.message_type == 4162 MyXA_DndPosition) 4163 { 4164 HandleClientMessageDndPosition(theEvent); 4165 } else if (theEvent->xclient.message_type == 4166 MyXA_DndDrop) 4167 { 4168 HandleClientMessageDndDrop(theEvent); 4169 } else 4170#endif 4171 { 4172 if ((32 == theEvent->xclient.format) && 4173 (theEvent->xclient.data.l[0] == MyXA_DeleteW)) 4174 { 4175 /* 4176 I would think that should test that 4177 WM_PROTOCOLS == message_type 4178 but none of the other programs I looked 4179 at did. 4180 */ 4181 RequestMacOff = trueblnr; 4182 } 4183 } 4184 } 4185 break; 4186 case FocusIn: 4187 if (theEvent->xfocus.window != my_main_wind) { 4188 WriteExtraErr("Got FocusIn for some other window"); 4189 } else { 4190#if MyDbgEvents 4191 dbglog_writeln("- event - FocusIn"); 4192#endif 4193 4194 gTrueBackgroundFlag = falseblnr; 4195#if UseMotionEvents 4196 CheckMouseState(); 4197 /* 4198 Doesn't help on x11 for OS X, 4199 can't get new mouse position 4200 in any fashion until mouse moves. 4201 */ 4202#endif 4203 } 4204 break; 4205 case FocusOut: 4206 if (theEvent->xfocus.window != my_main_wind) { 4207 WriteExtraErr("Got FocusOut for some other window"); 4208 } else { 4209#if MyDbgEvents 4210 dbglog_writeln("- event - FocusOut"); 4211#endif 4212 4213 gTrueBackgroundFlag = trueblnr; 4214 } 4215 break; 4216 default: 4217 break; 4218 } 4219} 4220 4221/* --- main window creation and disposal --- */ 4222 4223LOCALVAR int my_argc; 4224LOCALVAR char **my_argv; 4225 4226LOCALVAR char *display_name = NULL; 4227 4228LOCALFUNC blnr Screen_Init(void) 4229{ 4230 Window rootwin; 4231 int screen; 4232 Colormap Xcmap; 4233 Visual *Xvisual; 4234 4235 x_display = XOpenDisplay(display_name); 4236 if (NULL == x_display) { 4237 fprintf(stderr, "Cannot connect to X server.\n"); 4238 return falseblnr; 4239 } 4240 4241 screen = DefaultScreen(x_display); 4242 4243 rootwin = XRootWindow(x_display, screen); 4244 4245 Xcmap = DefaultColormap(x_display, screen); 4246 4247 Xvisual = DefaultVisual(x_display, screen); 4248 4249 LoadMyXA(); 4250 4251 XParseColor(x_display, Xcmap, "#000000", &x_black); 4252 if (! XAllocColor(x_display, Xcmap, &x_black)) { 4253 WriteExtraErr("XParseColor black fails"); 4254 } 4255 XParseColor(x_display, Xcmap, "#ffffff", &x_white); 4256 if (! XAllocColor(x_display, Xcmap, &x_white)) { 4257 WriteExtraErr("XParseColor white fails"); 4258 } 4259 4260 if (! CreateMyBlankCursor(rootwin)) { 4261 return falseblnr; 4262 } 4263 4264#if ! UseColorImage 4265 my_image = XCreateImage(x_display, Xvisual, 1, XYBitmap, 0, 4266 NULL /* (char *)image_Mem1 */, 4267 vMacScreenWidth, vMacScreenHeight, 32, 4268 vMacScreenMonoByteWidth); 4269 if (NULL == my_image) { 4270 fprintf(stderr, "XCreateImage failed.\n"); 4271 return falseblnr; 4272 } 4273 4274#if 0 4275 fprintf(stderr, "bitmap_bit_order = %d\n", 4276 (int)my_image->bitmap_bit_order); 4277 fprintf(stderr, "byte_order = %d\n", (int)my_image->byte_order); 4278#endif 4279 4280 my_image->bitmap_bit_order = MSBFirst; 4281 my_image->byte_order = MSBFirst; 4282#endif 4283 4284#if UseColorImage 4285 my_image = XCreateImage(x_display, Xvisual, 24, ZPixmap, 0, 4286 NULL /* (char *)image_Mem1 */, 4287 vMacScreenWidth, vMacScreenHeight, 32, 4288 4 * (ui5r)vMacScreenWidth); 4289 if (NULL == my_image) { 4290 fprintf(stderr, "XCreateImage Color failed.\n"); 4291 return falseblnr; 4292 } 4293 4294#if 0 4295 fprintf(stderr, "DefaultDepth = %d\n", 4296 (int)DefaultDepth(x_display, screen)); 4297 4298 fprintf(stderr, "MSBFirst = %d\n", (int)MSBFirst); 4299 fprintf(stderr, "LSBFirst = %d\n", (int)LSBFirst); 4300 4301 fprintf(stderr, "bitmap_bit_order = %d\n", 4302 (int)my_image->bitmap_bit_order); 4303 fprintf(stderr, "byte_order = %d\n", 4304 (int)my_image->byte_order); 4305 fprintf(stderr, "bitmap_unit = %d\n", 4306 (int)my_image->bitmap_unit); 4307 fprintf(stderr, "bits_per_pixel = %d\n", 4308 (int)my_image->bits_per_pixel); 4309 fprintf(stderr, "red_mask = %d\n", 4310 (int)my_image->red_mask); 4311 fprintf(stderr, "green_mask = %d\n", 4312 (int)my_image->green_mask); 4313 fprintf(stderr, "blue_mask = %d\n", 4314 (int)my_image->blue_mask); 4315#endif 4316 4317#endif /* UseColorImage */ 4318 4319#if EnableMagnify && (! UseColorImage) 4320 my_Scaled_image = XCreateImage(x_display, Xvisual, 4321 1, XYBitmap, 0, 4322 NULL /* (char *)image_Mem1 */, 4323 vMacScreenWidth * MyWindowScale, 4324 vMacScreenHeight * MyWindowScale, 4325 32, vMacScreenMonoByteWidth * MyWindowScale); 4326 if (NULL == my_Scaled_image) { 4327 fprintf(stderr, "XCreateImage failed.\n"); 4328 return falseblnr; 4329 } 4330 4331 my_Scaled_image->bitmap_bit_order = MSBFirst; 4332 my_Scaled_image->byte_order = MSBFirst; 4333#endif 4334 4335#if EnableMagnify && UseColorImage 4336 my_Scaled_image = XCreateImage(x_display, Xvisual, 4337 24, ZPixmap, 0, 4338 NULL /* (char *)image_Mem1 */, 4339 vMacScreenWidth * MyWindowScale, 4340 vMacScreenHeight * MyWindowScale, 4341 32, 4 * (ui5r)vMacScreenWidth * MyWindowScale); 4342 if (NULL == my_Scaled_image) { 4343 fprintf(stderr, "XCreateImage Scaled failed.\n"); 4344 return falseblnr; 4345 } 4346#endif 4347 4348#if 0 != vMacScreenDepth 4349 ColorModeWorks = trueblnr; 4350#endif 4351 4352 DisableKeyRepeat(); 4353 4354 return trueblnr; 4355} 4356 4357LOCALPROC CloseMainWindow(void) 4358{ 4359 if (my_gc != NULL) { 4360 XFreeGC(x_display, my_gc); 4361 my_gc = NULL; 4362 } 4363 if (my_main_wind) { 4364 XDestroyWindow(x_display, my_main_wind); 4365 my_main_wind = 0; 4366 } 4367} 4368 4369enum { 4370 kMagStateNormal, 4371#if EnableMagnify 4372 kMagStateMagnifgy, 4373#endif 4374 kNumMagStates 4375}; 4376 4377#define kMagStateAuto kNumMagStates 4378 4379#if MayNotFullScreen 4380LOCALVAR int CurWinIndx; 4381LOCALVAR blnr HavePositionWins[kNumMagStates]; 4382LOCALVAR int WinPositionWinsH[kNumMagStates]; 4383LOCALVAR int WinPositionWinsV[kNumMagStates]; 4384#endif 4385 4386#if EnableRecreateW 4387LOCALPROC ZapMyWState(void) 4388{ 4389 my_main_wind = 0; 4390 my_gc = NULL; 4391} 4392#endif 4393 4394LOCALFUNC blnr CreateMainWindow(void) 4395{ 4396 Window rootwin; 4397 int screen; 4398 int xr; 4399 int yr; 4400 unsigned int dr; 4401 unsigned int wr; 4402 unsigned int hr; 4403 unsigned int bwr; 4404 Window rr; 4405 int leftPos; 4406 int topPos; 4407#if MayNotFullScreen 4408 int WinIndx; 4409#endif 4410#if EnableDragDrop 4411 long int xdnd_version = 5; 4412#endif 4413 int NewWindowHeight = vMacScreenHeight; 4414 int NewWindowWidth = vMacScreenWidth; 4415 4416 /* Get connection to X Server */ 4417 screen = DefaultScreen(x_display); 4418 4419 rootwin = XRootWindow(x_display, screen); 4420 4421 XGetGeometry(x_display, rootwin, 4422 &rr, &xr, &yr, &wr, &hr, &bwr, &dr); 4423 4424#if EnableMagnify 4425 if (UseMagnify) { 4426 NewWindowHeight *= MyWindowScale; 4427 NewWindowWidth *= MyWindowScale; 4428 } 4429#endif 4430 4431 if (wr > NewWindowWidth) { 4432 leftPos = (wr - NewWindowWidth) / 2; 4433 } else { 4434 leftPos = 0; 4435 } 4436 if (hr > NewWindowHeight) { 4437 topPos = (hr - NewWindowHeight) / 2; 4438 } else { 4439 topPos = 0; 4440 } 4441 4442#if VarFullScreen 4443 if (UseFullScreen) 4444#endif 4445#if MayFullScreen 4446 { 4447 ViewHSize = wr; 4448 ViewVSize = hr; 4449#if EnableMagnify 4450 if (UseMagnify) { 4451 ViewHSize /= MyWindowScale; 4452 ViewVSize /= MyWindowScale; 4453 } 4454#endif 4455 if (ViewHSize >= vMacScreenWidth) { 4456 ViewHStart = 0; 4457 ViewHSize = vMacScreenWidth; 4458 } else { 4459 ViewHSize &= ~ 1; 4460 } 4461 if (ViewVSize >= vMacScreenHeight) { 4462 ViewVStart = 0; 4463 ViewVSize = vMacScreenHeight; 4464 } else { 4465 ViewVSize &= ~ 1; 4466 } 4467 } 4468#endif 4469 4470#if VarFullScreen 4471 if (! UseFullScreen) 4472#endif 4473#if MayNotFullScreen 4474 { 4475#if EnableMagnify 4476 if (UseMagnify) { 4477 WinIndx = kMagStateMagnifgy; 4478 } else 4479#endif 4480 { 4481 WinIndx = kMagStateNormal; 4482 } 4483 4484 if (! HavePositionWins[WinIndx]) { 4485 WinPositionWinsH[WinIndx] = leftPos; 4486 WinPositionWinsV[WinIndx] = topPos; 4487 HavePositionWins[WinIndx] = trueblnr; 4488 } else { 4489 leftPos = WinPositionWinsH[WinIndx]; 4490 topPos = WinPositionWinsV[WinIndx]; 4491 } 4492 } 4493#endif 4494 4495#if VarFullScreen 4496 if (UseFullScreen) 4497#endif 4498#if MayFullScreen 4499 { 4500 XSetWindowAttributes xattr; 4501 xattr.override_redirect = True; 4502 xattr.background_pixel = x_black.pixel; 4503 xattr.border_pixel = x_white.pixel; 4504 4505 my_main_wind = XCreateWindow(x_display, rr, 4506 0, 0, wr, hr, 0, 4507 CopyFromParent, /* depth */ 4508 InputOutput, /* class */ 4509 CopyFromParent, /* visual */ 4510 CWOverrideRedirect | CWBackPixel | CWBorderPixel, 4511 /* valuemask */ 4512 &xattr /* attributes */); 4513 } 4514#endif 4515#if VarFullScreen 4516 else 4517#endif 4518#if MayNotFullScreen 4519 { 4520 my_main_wind = XCreateSimpleWindow(x_display, rootwin, 4521 leftPos, 4522 topPos, 4523 NewWindowWidth, NewWindowHeight, 4, 4524 x_white.pixel, 4525 x_black.pixel); 4526 } 4527#endif 4528 4529 if (! my_main_wind) { 4530 WriteExtraErr("XCreateSimpleWindow failed."); 4531 return falseblnr; 4532 } else { 4533 char *win_name = 4534 (NULL != n_arg) ? n_arg : ( 4535#if CanGetAppPath 4536 (NULL != app_name) ? app_name : 4537#endif 4538 kStrAppName); 4539 XSelectInput(x_display, my_main_wind, 4540 ExposureMask | KeyPressMask | KeyReleaseMask 4541 | ButtonPressMask | ButtonReleaseMask 4542#if UseMotionEvents 4543 | PointerMotionMask | EnterWindowMask | LeaveWindowMask 4544#endif 4545 | FocusChangeMask); 4546 4547 XStoreName(x_display, my_main_wind, win_name); 4548 XSetIconName(x_display, my_main_wind, win_name); 4549 4550 { 4551 XClassHint *hints = XAllocClassHint(); 4552 if (hints) { 4553 hints->res_name = "minivmac"; 4554 hints->res_class = "minivmac"; 4555 XSetClassHint(x_display, my_main_wind, hints); 4556 XFree(hints); 4557 } 4558 } 4559 4560 { 4561 XWMHints *hints = XAllocWMHints(); 4562 if (hints) { 4563 hints->input = True; 4564 hints->initial_state = NormalState; 4565 hints->flags = InputHint | StateHint; 4566 XSetWMHints(x_display, my_main_wind, hints); 4567 XFree(hints); 4568 } 4569 4570 } 4571 4572 XSetCommand(x_display, my_main_wind, my_argv, my_argc); 4573 4574 /* let us handle a click on the close box */ 4575 XSetWMProtocols(x_display, my_main_wind, &MyXA_DeleteW, 1); 4576 4577#if EnableDragDrop 4578 XChangeProperty (x_display, my_main_wind, MyXA_DndAware, 4579 XA_ATOM, 32, PropModeReplace, 4580 (unsigned char *) &xdnd_version, 1); 4581#endif 4582 4583 my_gc = XCreateGC(x_display, my_main_wind, 0, NULL); 4584 if (NULL == my_gc) { 4585 WriteExtraErr("XCreateGC failed."); 4586 return falseblnr; 4587 } 4588 XSetState(x_display, my_gc, x_black.pixel, x_white.pixel, 4589 GXcopy, AllPlanes); 4590 4591#if VarFullScreen 4592 if (! UseFullScreen) 4593#endif 4594#if MayNotFullScreen 4595 { 4596 XSizeHints *hints = XAllocSizeHints(); 4597 if (hints) { 4598 hints->min_width = NewWindowWidth; 4599 hints->max_width = NewWindowWidth; 4600 hints->min_height = NewWindowHeight; 4601 hints->max_height = NewWindowHeight; 4602 4603 /* 4604 Try again to say where the window ought to go. 4605 I've seen this described as obsolete, but it 4606 seems to work on all x implementations tried 4607 so far, and nothing else does. 4608 */ 4609 hints->x = leftPos; 4610 hints->y = topPos; 4611 hints->width = NewWindowWidth; 4612 hints->height = NewWindowHeight; 4613 4614 hints->flags = PMinSize | PMaxSize | PPosition | PSize; 4615 XSetWMNormalHints(x_display, my_main_wind, hints); 4616 XFree(hints); 4617 } 4618 } 4619#endif 4620 4621#if VarFullScreen 4622 if (UseFullScreen) 4623#endif 4624#if MayFullScreen 4625 { 4626 hOffset = leftPos; 4627 vOffset = topPos; 4628 } 4629#endif 4630 4631 DisconnectKeyCodes3(); 4632 /* since will lose keystrokes to old window */ 4633 4634#if MayNotFullScreen 4635 CurWinIndx = WinIndx; 4636#endif 4637 4638 XMapRaised(x_display, my_main_wind); 4639 4640#if 0 4641 XSync(x_display, 0); 4642#endif 4643 4644#if 0 4645 /* 4646 This helps in Red Hat 9 to get the new window 4647 activated, and I've seen other programs 4648 do similar things. 4649 */ 4650 /* 4651 In current scheme, haven't closed old window 4652 yet. If old window full screen, never receive 4653 expose event for new one. 4654 */ 4655 { 4656 XEvent event; 4657 4658 do { 4659 XNextEvent(x_display, &event); 4660 HandleTheEvent(&event); 4661 } while (! ((Expose == event.type) 4662 && (event.xexpose.window == my_main_wind))); 4663 } 4664#endif 4665 4666 NeedFinishOpen1 = trueblnr; 4667 NeedFinishOpen2 = trueblnr; 4668 4669 return trueblnr; 4670 } 4671} 4672 4673#if MayFullScreen 4674LOCALVAR blnr GrabMachine = falseblnr; 4675#endif 4676 4677#if MayFullScreen 4678LOCALPROC GrabTheMachine(void) 4679{ 4680#if EnableFSMouseMotion 4681 StartSaveMouseMotion(); 4682#endif 4683#if GrabKeysFullScreen 4684 MyGrabKeyboard(); 4685#endif 4686} 4687#endif 4688 4689#if MayFullScreen 4690LOCALPROC UngrabMachine(void) 4691{ 4692#if EnableFSMouseMotion 4693 StopSaveMouseMotion(); 4694#endif 4695#if GrabKeysFullScreen 4696 MyUnGrabKeyboard(); 4697#endif 4698} 4699#endif 4700 4701#if EnableRecreateW 4702struct MyWState { 4703 Window f_my_main_wind; 4704 GC f_my_gc; 4705#if MayFullScreen 4706 short f_hOffset; 4707 short f_vOffset; 4708 ui4r f_ViewHSize; 4709 ui4r f_ViewVSize; 4710 ui4r f_ViewHStart; 4711 ui4r f_ViewVStart; 4712#endif 4713#if VarFullScreen 4714 blnr f_UseFullScreen; 4715#endif 4716#if EnableMagnify 4717 blnr f_UseMagnify; 4718#endif 4719}; 4720typedef struct MyWState MyWState; 4721#endif 4722 4723#if EnableRecreateW 4724LOCALPROC GetMyWState(MyWState *r) 4725{ 4726 r->f_my_main_wind = my_main_wind; 4727 r->f_my_gc = my_gc; 4728#if MayFullScreen 4729 r->f_hOffset = hOffset; 4730 r->f_vOffset = vOffset; 4731 r->f_ViewHSize = ViewHSize; 4732 r->f_ViewVSize = ViewVSize; 4733 r->f_ViewHStart = ViewHStart; 4734 r->f_ViewVStart = ViewVStart; 4735#endif 4736#if VarFullScreen 4737 r->f_UseFullScreen = UseFullScreen; 4738#endif 4739#if EnableMagnify 4740 r->f_UseMagnify = UseMagnify; 4741#endif 4742} 4743#endif 4744 4745#if EnableRecreateW 4746LOCALPROC SetMyWState(MyWState *r) 4747{ 4748 my_main_wind = r->f_my_main_wind; 4749 my_gc = r->f_my_gc; 4750#if MayFullScreen 4751 hOffset = r->f_hOffset; 4752 vOffset = r->f_vOffset; 4753 ViewHSize = r->f_ViewHSize; 4754 ViewVSize = r->f_ViewVSize; 4755 ViewHStart = r->f_ViewHStart; 4756 ViewVStart = r->f_ViewVStart; 4757#endif 4758#if VarFullScreen 4759 UseFullScreen = r->f_UseFullScreen; 4760#endif 4761#if EnableMagnify 4762 UseMagnify = r->f_UseMagnify; 4763#endif 4764} 4765#endif 4766 4767#if EnableRecreateW 4768LOCALVAR blnr WantRestoreCursPos = falseblnr; 4769LOCALVAR ui4b RestoreMouseH; 4770LOCALVAR ui4b RestoreMouseV; 4771#endif 4772 4773#if EnableRecreateW 4774LOCALFUNC blnr ReCreateMainWindow(void) 4775{ 4776 MyWState old_state; 4777 MyWState new_state; 4778#if IncludeHostTextClipExchange 4779 blnr OwnClipboard = falseblnr; 4780#endif 4781 4782 if (HaveCursorHidden) { 4783 WantRestoreCursPos = trueblnr; 4784 RestoreMouseH = CurMouseH; 4785 RestoreMouseV = CurMouseV; 4786 } 4787 4788 ForceShowCursor(); /* hide/show cursor api is per window */ 4789 4790#if MayNotFullScreen 4791#if VarFullScreen 4792 if (! UseFullScreen) 4793#endif 4794 if (my_main_wind) 4795 if (! NeedFinishOpen2) 4796 { 4797 /* save old position */ 4798 int xr; 4799 int yr; 4800 unsigned int dr; 4801 unsigned int wr; 4802 unsigned int hr; 4803 unsigned int bwr; 4804 Window rr; 4805 Window rr2; 4806 4807 /* Get connection to X Server */ 4808 int screen = DefaultScreen(x_display); 4809 4810 Window rootwin = XRootWindow(x_display, screen); 4811 4812 XGetGeometry(x_display, rootwin, 4813 &rr, &xr, &yr, &wr, &hr, &bwr, &dr); 4814 4815 /* 4816 Couldn't reliably find out where window 4817 is now, due to what seem to be some 4818 broken X implementations, and so instead 4819 track how far window has moved. 4820 */ 4821 XSync(x_display, 0); 4822 if (XTranslateCoordinates(x_display, my_main_wind, rootwin, 4823 0, 0, &xr, &yr, &rr2)) 4824 { 4825 int newposh = 4826 WinPositionWinsH[CurWinIndx] + (xr - SavedTransH); 4827 int newposv = 4828 WinPositionWinsV[CurWinIndx] + (yr - SavedTransV); 4829 if ((newposv > 0) && (newposv < hr) && (newposh < wr)) { 4830 WinPositionWinsH[CurWinIndx] = newposh; 4831 WinPositionWinsV[CurWinIndx] = newposv; 4832 SavedTransH = xr; 4833 SavedTransV = yr; 4834 } 4835 } 4836 } 4837#endif 4838 4839#if MayFullScreen 4840 if (GrabMachine) { 4841 GrabMachine = falseblnr; 4842 UngrabMachine(); 4843 } 4844#endif 4845 4846 GetMyWState(&old_state); 4847 ZapMyWState(); 4848 4849#if EnableMagnify 4850 UseMagnify = WantMagnify; 4851#endif 4852#if VarFullScreen 4853 UseFullScreen = WantFullScreen; 4854#endif 4855 4856 ColorTransValid = falseblnr; 4857 4858 if (! CreateMainWindow()) { 4859 CloseMainWindow(); 4860 SetMyWState(&old_state); 4861 4862 /* avoid retry */ 4863#if VarFullScreen 4864 WantFullScreen = UseFullScreen; 4865#endif 4866#if EnableMagnify 4867 WantMagnify = UseMagnify; 4868#endif 4869 4870 return falseblnr; 4871 } else { 4872 GetMyWState(&new_state); 4873 SetMyWState(&old_state); 4874 4875#if IncludeHostTextClipExchange 4876 if (my_main_wind) { 4877 if (XGetSelectionOwner(x_display, MyXA_CLIPBOARD) == 4878 my_main_wind) 4879 { 4880 OwnClipboard = trueblnr; 4881 } 4882 } 4883#endif 4884 4885 CloseMainWindow(); 4886 4887 SetMyWState(&new_state); 4888 4889#if IncludeHostTextClipExchange 4890 if (OwnClipboard) { 4891 XSetSelectionOwner(x_display, MyXA_CLIPBOARD, 4892 my_main_wind, CurrentTime); 4893 } 4894#endif 4895 } 4896 4897 return trueblnr; 4898} 4899#endif 4900 4901#if VarFullScreen && EnableMagnify 4902enum { 4903 kWinStateWindowed, 4904#if EnableMagnify 4905 kWinStateFullScreen, 4906#endif 4907 kNumWinStates 4908}; 4909#endif 4910 4911#if VarFullScreen && EnableMagnify 4912LOCALVAR int WinMagStates[kNumWinStates]; 4913#endif 4914 4915LOCALPROC ZapWinStateVars(void) 4916{ 4917#if MayNotFullScreen 4918 { 4919 int i; 4920 4921 for (i = 0; i < kNumMagStates; ++i) { 4922 HavePositionWins[i] = falseblnr; 4923 } 4924 } 4925#endif 4926#if VarFullScreen && EnableMagnify 4927 { 4928 int i; 4929 4930 for (i = 0; i < kNumWinStates; ++i) { 4931 WinMagStates[i] = kMagStateAuto; 4932 } 4933 } 4934#endif 4935} 4936 4937#if VarFullScreen 4938LOCALPROC ToggleWantFullScreen(void) 4939{ 4940 WantFullScreen = ! WantFullScreen; 4941 4942#if EnableMagnify 4943 { 4944 int OldWinState = 4945 UseFullScreen ? kWinStateFullScreen : kWinStateWindowed; 4946 int OldMagState = 4947 UseMagnify ? kMagStateMagnifgy : kMagStateNormal; 4948 int NewWinState = 4949 WantFullScreen ? kWinStateFullScreen : kWinStateWindowed; 4950 int NewMagState = WinMagStates[NewWinState]; 4951 4952 WinMagStates[OldWinState] = OldMagState; 4953 if (kMagStateAuto != NewMagState) { 4954 WantMagnify = (kMagStateMagnifgy == NewMagState); 4955 } else { 4956 WantMagnify = falseblnr; 4957 if (WantFullScreen) { 4958 Window rootwin; 4959 int xr; 4960 int yr; 4961 unsigned int dr; 4962 unsigned int wr; 4963 unsigned int hr; 4964 unsigned int bwr; 4965 Window rr; 4966 4967 rootwin = 4968 XRootWindow(x_display, DefaultScreen(x_display)); 4969 XGetGeometry(x_display, rootwin, 4970 &rr, &xr, &yr, &wr, &hr, &bwr, &dr); 4971 if ((wr >= vMacScreenWidth * MyWindowScale) 4972 && (hr >= vMacScreenHeight * MyWindowScale) 4973 ) 4974 { 4975 WantMagnify = trueblnr; 4976 } 4977 } 4978 } 4979 } 4980#endif 4981} 4982#endif 4983 4984/* --- SavedTasks --- */ 4985 4986LOCALPROC LeaveBackground(void) 4987{ 4988 ReconnectKeyCodes3(); 4989 DisableKeyRepeat(); 4990} 4991 4992LOCALPROC EnterBackground(void) 4993{ 4994 RestoreKeyRepeat(); 4995 DisconnectKeyCodes3(); 4996 4997 ForceShowCursor(); 4998} 4999 5000LOCALPROC LeaveSpeedStopped(void) 5001{ 5002#if MySoundEnabled 5003 MySound_Start(); 5004#endif 5005 5006 StartUpTimeAdjust(); 5007} 5008 5009LOCALPROC EnterSpeedStopped(void) 5010{ 5011#if MySoundEnabled 5012 MySound_Stop(); 5013#endif 5014} 5015 5016LOCALPROC CheckForSavedTasks(void) 5017{ 5018 if (MyEvtQNeedRecover) { 5019 MyEvtQNeedRecover = falseblnr; 5020 5021 /* attempt cleanup, MyEvtQNeedRecover may get set again */ 5022 MyEvtQTryRecoverFromFull(); 5023 } 5024 5025 if (NeedFinishOpen2 && ! NeedFinishOpen1) { 5026 NeedFinishOpen2 = falseblnr; 5027 5028#if VarFullScreen 5029 if (UseFullScreen) 5030#endif 5031#if MayFullScreen 5032 { 5033 XSetInputFocus(x_display, my_main_wind, 5034 RevertToPointerRoot, CurrentTime); 5035 } 5036#endif 5037#if VarFullScreen 5038 else 5039#endif 5040#if MayNotFullScreen 5041 { 5042 Window rr; 5043 int screen = DefaultScreen(x_display); 5044 Window rootwin = XRootWindow(x_display, screen); 5045#if 0 5046 /* 5047 This doesn't work right in Red Hat 6, and may not 5048 be needed anymore, now that using PPosition hint. 5049 */ 5050 XMoveWindow(x_display, my_main_wind, 5051 leftPos, topPos); 5052 /* 5053 Needed after XMapRaised, because some window 5054 managers will apparently ignore where the 5055 window was asked to be put. 5056 */ 5057#endif 5058 5059 XSync(x_display, 0); 5060 /* 5061 apparently, XTranslateCoordinates can be inaccurate 5062 without this 5063 */ 5064 XTranslateCoordinates(x_display, my_main_wind, rootwin, 5065 0, 0, &SavedTransH, &SavedTransV, &rr); 5066 } 5067#endif 5068 5069#if EnableRecreateW 5070 if (WantRestoreCursPos) { 5071#if EnableFSMouseMotion 5072 if (! HaveMouseMotion) 5073#endif 5074 { 5075 (void) MyMoveMouse(RestoreMouseH, RestoreMouseV); 5076 WantCursorHidden = trueblnr; 5077 } 5078 WantRestoreCursPos = falseblnr; 5079 } 5080#endif 5081 } 5082 5083#if EnableFSMouseMotion 5084 if (HaveMouseMotion) { 5085 MyMouseConstrain(); 5086 } 5087#endif 5088 5089 if (RequestMacOff) { 5090 RequestMacOff = falseblnr; 5091 if (AnyDiskInserted()) { 5092 MacMsgOverride(kStrQuitWarningTitle, 5093 kStrQuitWarningMessage); 5094 } else { 5095 ForceMacOff = trueblnr; 5096 } 5097 } 5098 5099 if (ForceMacOff) { 5100 return; 5101 } 5102 5103 if (gTrueBackgroundFlag != gBackgroundFlag) { 5104 gBackgroundFlag = gTrueBackgroundFlag; 5105 if (gTrueBackgroundFlag) { 5106 EnterBackground(); 5107 } else { 5108 LeaveBackground(); 5109 } 5110 } 5111 5112 if (CurSpeedStopped != (SpeedStopped || 5113 (gBackgroundFlag && ! RunInBackground 5114#if EnableAutoSlow && 0 5115 && (QuietSubTicks >= 4092) 5116#endif 5117 ))) 5118 { 5119 CurSpeedStopped = ! CurSpeedStopped; 5120 if (CurSpeedStopped) { 5121 EnterSpeedStopped(); 5122 } else { 5123 LeaveSpeedStopped(); 5124 } 5125 } 5126 5127#if MayFullScreen 5128 if (gTrueBackgroundFlag 5129#if VarFullScreen 5130 && WantFullScreen 5131#endif 5132 ) 5133 { 5134 /* 5135 Since often get here on Ubuntu Linux 5.10 5136 running on a slow machine (emulated) when 5137 attempt to enter full screen, don't abort 5138 full screen, but try to fix it. 5139 */ 5140#if 0 5141 ToggleWantFullScreen(); 5142#else 5143 XRaiseWindow(x_display, my_main_wind); 5144 XSetInputFocus(x_display, my_main_wind, 5145 RevertToPointerRoot, CurrentTime); 5146#endif 5147 } 5148#endif 5149 5150#if EnableRecreateW 5151 if (0 5152#if EnableMagnify 5153 || (UseMagnify != WantMagnify) 5154#endif 5155#if VarFullScreen 5156 || (UseFullScreen != WantFullScreen) 5157#endif 5158 ) 5159 { 5160 (void) ReCreateMainWindow(); 5161 } 5162#endif 5163 5164 5165#if MayFullScreen 5166 if (GrabMachine != ( 5167#if VarFullScreen 5168 UseFullScreen && 5169#endif 5170 ! (gTrueBackgroundFlag || CurSpeedStopped))) 5171 { 5172 GrabMachine = ! GrabMachine; 5173 if (GrabMachine) { 5174 GrabTheMachine(); 5175 } else { 5176 UngrabMachine(); 5177 } 5178 } 5179#endif 5180 5181#if IncludeSonyNew 5182 if (vSonyNewDiskWanted) { 5183#if IncludeSonyNameNew 5184 if (vSonyNewDiskName != NotAPbuf) { 5185 ui3p NewDiskNameDat; 5186 if (MacRomanTextToNativePtr(vSonyNewDiskName, trueblnr, 5187 &NewDiskNameDat)) 5188 { 5189 MakeNewDisk(vSonyNewDiskSize, (char *)NewDiskNameDat); 5190 free(NewDiskNameDat); 5191 } 5192 PbufDispose(vSonyNewDiskName); 5193 vSonyNewDiskName = NotAPbuf; 5194 } else 5195#endif 5196 { 5197 MakeNewDiskAtDefault(vSonyNewDiskSize); 5198 } 5199 vSonyNewDiskWanted = falseblnr; 5200 /* must be done after may have gotten disk */ 5201 } 5202#endif 5203 5204 if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) { 5205 MacMsgDisplayOn(); 5206 } 5207 5208 if (NeedWholeScreenDraw) { 5209 NeedWholeScreenDraw = falseblnr; 5210 ScreenChangedAll(); 5211 } 5212 5213#if NeedRequestIthDisk 5214 if (0 != RequestIthDisk) { 5215 Sony_InsertIth(RequestIthDisk); 5216 RequestIthDisk = 0; 5217 } 5218#endif 5219 5220 if (HaveCursorHidden != (WantCursorHidden 5221 && ! (gTrueBackgroundFlag || CurSpeedStopped))) 5222 { 5223 HaveCursorHidden = ! HaveCursorHidden; 5224 if (HaveCursorHidden) { 5225 XDefineCursor(x_display, my_main_wind, blankCursor); 5226 } else { 5227 XUndefineCursor(x_display, my_main_wind); 5228 } 5229 } 5230} 5231 5232/* --- command line parsing --- */ 5233 5234LOCALFUNC blnr ScanCommandLine(void) 5235{ 5236 char *pa; 5237 int i = 1; 5238 5239label_retry: 5240 if (i < my_argc) { 5241 pa = my_argv[i++]; 5242 if ('-' == pa[0]) { 5243 if ((0 == strcmp(pa, "--display")) 5244 || (0 == strcmp(pa, "-display"))) 5245 { 5246 if (i < my_argc) { 5247 display_name = my_argv[i++]; 5248 goto label_retry; 5249 } 5250 } else 5251 if ((0 == strcmp(pa, "--rom")) 5252 || (0 == strcmp(pa, "-r"))) 5253 { 5254 if (i < my_argc) { 5255 rom_path = my_argv[i++]; 5256 goto label_retry; 5257 } 5258 } else 5259 if (0 == strcmp(pa, "-n")) 5260 { 5261 if (i < my_argc) { 5262 n_arg = my_argv[i++]; 5263 goto label_retry; 5264 } 5265 } else 5266 if (0 == strcmp(pa, "-d")) 5267 { 5268 if (i < my_argc) { 5269 d_arg = my_argv[i++]; 5270 goto label_retry; 5271 } 5272 } else 5273#ifndef UsingAlsa 5274#define UsingAlsa 0 5275#endif 5276 5277#if UsingAlsa 5278 if ((0 == strcmp(pa, "--alsadev")) 5279 || (0 == strcmp(pa, "-alsadev"))) 5280 { 5281 if (i < my_argc) { 5282 alsadev_name = my_argv[i++]; 5283 goto label_retry; 5284 } 5285 } else 5286#endif 5287#if 0 5288 if (0 == strcmp(pa, "-l")) { 5289 SpeedValue = 0; 5290 goto label_retry; 5291 } else 5292#endif 5293 { 5294 MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr); 5295 } 5296 } else { 5297 (void) Sony_Insert1(pa, falseblnr); 5298 goto label_retry; 5299 } 5300 } 5301 5302 return trueblnr; 5303} 5304 5305/* --- main program flow --- */ 5306 5307GLOBALOSGLUPROC DoneWithDrawingForTick(void) 5308{ 5309#if EnableFSMouseMotion 5310 if (HaveMouseMotion) { 5311 AutoScrollScreen(); 5312 } 5313#endif 5314 MyDrawChangesAndClear(); 5315 XFlush(x_display); 5316} 5317 5318GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void) 5319{ 5320 UpdateTrueEmulatedTime(); 5321 return TrueEmulatedTime == OnTrueTime; 5322} 5323 5324LOCALPROC WaitForTheNextEvent(void) 5325{ 5326 XEvent event; 5327 5328 XNextEvent(x_display, &event); 5329 HandleTheEvent(&event); 5330} 5331 5332LOCALPROC CheckForSystemEvents(void) 5333{ 5334 int i = 10; 5335 5336 while ((XEventsQueued(x_display, QueuedAfterReading) > 0) 5337 && (--i >= 0)) 5338 { 5339 WaitForTheNextEvent(); 5340 } 5341} 5342 5343GLOBALOSGLUPROC WaitForNextTick(void) 5344{ 5345label_retry: 5346 CheckForSystemEvents(); 5347 CheckForSavedTasks(); 5348 if (ForceMacOff) { 5349 return; 5350 } 5351 5352 if (CurSpeedStopped) { 5353 DoneWithDrawingForTick(); 5354 WaitForTheNextEvent(); 5355 goto label_retry; 5356 } 5357 5358 if (ExtraTimeNotOver()) { 5359 struct timespec rqt; 5360 struct timespec rmt; 5361 5362 si5b TimeDiff = GetTimeDiff(); 5363 if (TimeDiff < 0) { 5364 rqt.tv_sec = 0; 5365 rqt.tv_nsec = (- TimeDiff) * 1000; 5366 (void) nanosleep(&rqt, &rmt); 5367 } 5368 goto label_retry; 5369 } 5370 5371 if (CheckDateTime()) { 5372#if MySoundEnabled 5373 MySound_SecondNotify(); 5374#endif 5375#if EnableDemoMsg 5376 DemoModeSecondNotify(); 5377#endif 5378 } 5379 5380 if ((! gBackgroundFlag) 5381#if UseMotionEvents 5382 && (! CaughtMouse) 5383#endif 5384 ) 5385 { 5386 CheckMouseState(); 5387 } 5388 5389 OnTrueTime = TrueEmulatedTime; 5390 5391#if dbglog_TimeStuff 5392 dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime); 5393#endif 5394} 5395 5396/* --- platform independent code can be thought of as going here --- */ 5397 5398#include "PROGMAIN.h" 5399 5400LOCALPROC ZapOSGLUVars(void) 5401{ 5402 InitDrives(); 5403 ZapWinStateVars(); 5404} 5405 5406LOCALPROC ReserveAllocAll(void) 5407{ 5408#if dbglog_HAVE 5409 dbglog_ReserveAlloc(); 5410#endif 5411 ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr); 5412 5413 ReserveAllocOneBlock(&screencomparebuff, 5414 vMacScreenNumBytes, 5, trueblnr); 5415#if UseControlKeys 5416 ReserveAllocOneBlock(&CntrlDisplayBuff, 5417 vMacScreenNumBytes, 5, falseblnr); 5418#endif 5419#if WantScalingBuff 5420 ReserveAllocOneBlock(&ScalingBuff, 5421 ScalingBuffsz, 5, falseblnr); 5422#endif 5423#if WantScalingTabl 5424 ReserveAllocOneBlock(&ScalingTabl, 5425 ScalingTablsz, 5, falseblnr); 5426#endif 5427 5428#if MySoundEnabled 5429 ReserveAllocOneBlock((ui3p *)&TheSoundBuffer, 5430 dbhBufferSize, 5, falseblnr); 5431#endif 5432 5433 EmulationReserveAlloc(); 5434} 5435 5436LOCALFUNC blnr AllocMyMemory(void) 5437{ 5438 uimr n; 5439 blnr IsOk = falseblnr; 5440 5441 ReserveAllocOffset = 0; 5442 ReserveAllocBigBlock = nullpr; 5443 ReserveAllocAll(); 5444 n = ReserveAllocOffset; 5445 ReserveAllocBigBlock = (ui3p)calloc(1, n); 5446 if (NULL == ReserveAllocBigBlock) { 5447 MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr); 5448 } else { 5449 ReserveAllocOffset = 0; 5450 ReserveAllocAll(); 5451 if (n != ReserveAllocOffset) { 5452 /* oops, program error */ 5453 } else { 5454 IsOk = trueblnr; 5455 } 5456 } 5457 5458 return IsOk; 5459} 5460 5461LOCALPROC UnallocMyMemory(void) 5462{ 5463 if (nullpr != ReserveAllocBigBlock) { 5464 free((char *)ReserveAllocBigBlock); 5465 } 5466} 5467 5468#if HaveAppPathLink 5469LOCALFUNC blnr ReadLink_Alloc(char *path, char **r) 5470{ 5471 /* 5472 This should work to find size: 5473 5474 struct stat r; 5475 5476 if (lstat(path, &r) != -1) { 5477 r = r.st_size; 5478 IsOk = trueblnr; 5479 } 5480 5481 But observed to return 0 in Ubuntu 10.04 x86-64 5482 */ 5483 5484 char *s; 5485 int sz; 5486 char *p; 5487 blnr IsOk = falseblnr; 5488 size_t s_alloc = 256; 5489 5490label_retry: 5491 s = (char *)malloc(s_alloc); 5492 if (NULL == s) { 5493 fprintf(stderr, "malloc failed.\n"); 5494 } else { 5495 sz = readlink(path, s, s_alloc); 5496 if ((sz < 0) || (sz >= s_alloc)) { 5497 free(s); 5498 if (sz == s_alloc) { 5499 s_alloc <<= 1; 5500 goto label_retry; 5501 } else { 5502 fprintf(stderr, "readlink failed.\n"); 5503 } 5504 } else { 5505 /* ok */ 5506 p = (char *)malloc(sz + 1); 5507 if (NULL == p) { 5508 fprintf(stderr, "malloc failed.\n"); 5509 } else { 5510 (void) memcpy(p, s, sz); 5511 p[sz] = 0; 5512 *r = p; 5513 IsOk = trueblnr; 5514 } 5515 free(s); 5516 } 5517 } 5518 5519 return IsOk; 5520} 5521#endif 5522 5523#if HaveSysctlPath 5524LOCALFUNC blnr ReadKernProcPathname(char **r) 5525{ 5526 size_t s_alloc; 5527 char *s; 5528 int mib[] = { 5529 CTL_KERN, 5530 KERN_PROC, 5531 KERN_PROC_PATHNAME, 5532 -1 5533 }; 5534 blnr IsOk = falseblnr; 5535 5536 if (0 != sysctl(mib, sizeof(mib) / sizeof(int), 5537 NULL, &s_alloc, NULL, 0)) 5538 { 5539 fprintf(stderr, "sysctl failed.\n"); 5540 } else { 5541 s = (char *)malloc(s_alloc); 5542 if (NULL == s) { 5543 fprintf(stderr, "malloc failed.\n"); 5544 } else { 5545 if (0 != sysctl(mib, sizeof(mib) / sizeof(int), 5546 s, &s_alloc, NULL, 0)) 5547 { 5548 fprintf(stderr, "sysctl 2 failed.\n"); 5549 } else { 5550 *r = s; 5551 IsOk = trueblnr; 5552 } 5553 if (! IsOk) { 5554 free(s); 5555 } 5556 } 5557 } 5558 5559 return IsOk; 5560} 5561#endif 5562 5563#if CanGetAppPath 5564LOCALFUNC blnr Path2ParentAndName(char *path, 5565 char **parent, char **name) 5566{ 5567 blnr IsOk = falseblnr; 5568 5569 char *t = strrchr(path, '/'); 5570 if (NULL == t) { 5571 fprintf(stderr, "no directory.\n"); 5572 } else { 5573 int par_sz = t - path; 5574 char *par = (char *)malloc(par_sz + 1); 5575 if (NULL == par) { 5576 fprintf(stderr, "malloc failed.\n"); 5577 } else { 5578 (void) memcpy(par, path, par_sz); 5579 par[par_sz] = 0; 5580 { 5581 int s_sz = strlen(path); 5582 int child_sz = s_sz - par_sz - 1; 5583 char *child = (char *)malloc(child_sz + 1); 5584 if (NULL == child) { 5585 fprintf(stderr, "malloc failed.\n"); 5586 } else { 5587 (void) memcpy(child, t + 1, child_sz); 5588 child[child_sz] = 0; 5589 5590 *name = child; 5591 IsOk = trueblnr; 5592 /* free(child); */ 5593 } 5594 } 5595 if (! IsOk) { 5596 free(par); 5597 } else { 5598 *parent = par; 5599 } 5600 } 5601 } 5602 5603 return IsOk; 5604} 5605#endif 5606 5607#if CanGetAppPath 5608LOCALFUNC blnr InitWhereAmI(void) 5609{ 5610 char *s; 5611 5612 if (! 5613#if HaveAppPathLink 5614 ReadLink_Alloc(TheAppPathLink, &s) 5615#endif 5616#if HaveSysctlPath 5617 ReadKernProcPathname(&s) 5618#endif 5619 ) 5620 { 5621 fprintf(stderr, "InitWhereAmI fails.\n"); 5622 } else { 5623 if (! Path2ParentAndName(s, &app_parent, &app_name)) { 5624 fprintf(stderr, "Path2ParentAndName fails.\n"); 5625 } else { 5626 /* ok */ 5627 /* 5628 fprintf(stderr, "parent = %s.\n", app_parent); 5629 fprintf(stderr, "name = %s.\n", app_name); 5630 */ 5631 } 5632 5633 free(s); 5634 } 5635 5636 return trueblnr; /* keep going regardless */ 5637} 5638#endif 5639 5640#if CanGetAppPath 5641LOCALPROC UninitWhereAmI(void) 5642{ 5643 MyMayFree(app_parent); 5644 MyMayFree(app_name); 5645} 5646#endif 5647 5648LOCALFUNC blnr InitOSGLU(void) 5649{ 5650 if (AllocMyMemory()) 5651#if CanGetAppPath 5652 if (InitWhereAmI()) 5653#endif 5654#if dbglog_HAVE 5655 if (dbglog_open()) 5656#endif 5657 if (ScanCommandLine()) 5658 if (LoadMacRom()) 5659 if (LoadInitialImages()) 5660#if UseActvCode 5661 if (ActvCodeInit()) 5662#endif 5663 if (InitLocationDat()) 5664#if MySoundEnabled 5665 if (MySound_Init()) 5666#endif 5667 if (Screen_Init()) 5668 if (CreateMainWindow()) 5669 if (KC2MKCInit()) 5670#if EmLocalTalk 5671 if (EntropyGather()) 5672 if (InitLocalTalk()) 5673#endif 5674 if (WaitForRom()) 5675 { 5676 return trueblnr; 5677 } 5678 return falseblnr; 5679} 5680 5681LOCALPROC UnInitOSGLU(void) 5682{ 5683 if (MacMsgDisplayed) { 5684 MacMsgDisplayOff(); 5685 } 5686 5687#if EmLocalTalk 5688 UnInitLocalTalk(); 5689#endif 5690 5691 RestoreKeyRepeat(); 5692#if MayFullScreen 5693 UngrabMachine(); 5694#endif 5695#if MySoundEnabled 5696 MySound_Stop(); 5697#endif 5698#if MySoundEnabled 5699 MySound_UnInit(); 5700#endif 5701#if IncludeHostTextClipExchange 5702 FreeMyClipBuffer(); 5703#endif 5704#if IncludePbufs 5705 UnInitPbufs(); 5706#endif 5707 UnInitDrives(); 5708 5709 ForceShowCursor(); 5710 if (blankCursor != None) { 5711 XFreeCursor(x_display, blankCursor); 5712 } 5713 5714 if (my_image != NULL) { 5715 XDestroyImage(my_image); 5716 } 5717#if EnableMagnify 5718 if (my_Scaled_image != NULL) { 5719 XDestroyImage(my_Scaled_image); 5720 } 5721#endif 5722 5723 CloseMainWindow(); 5724 if (x_display != NULL) { 5725 XCloseDisplay(x_display); 5726 } 5727 5728#if dbglog_HAVE 5729 dbglog_close(); 5730#endif 5731 5732#if CanGetAppPath 5733 UninitWhereAmI(); 5734#endif 5735 UnallocMyMemory(); 5736 5737 CheckSavedMacMsg(); 5738} 5739 5740int main(int argc, char **argv) 5741{ 5742 my_argc = argc; 5743 my_argv = argv; 5744 5745 ZapOSGLUVars(); 5746 if (InitOSGLU()) { 5747 ProgramMain(); 5748 } 5749 UnInitOSGLU(); 5750 5751 return 0; 5752} 5753 5754#endif /* WantOSGLUXWN */