diff --git a/CMakeLists.txt b/CMakeLists.txt index a859289b..0d49b739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,10 @@ elseif(PDC_X11_BUILD) # set(PDC_WIDE ON) add_subdirectory(x11new) +elseif(CMAKE_SYSTEM_NAME MATCHES "^Retro") + + add_subdirectory(mac) + else() add_subdirectory(ncurses) diff --git a/cmake/project_common.cmake b/cmake/project_common.cmake index 48e4f09d..789d834f 100644 --- a/cmake/project_common.cmake +++ b/cmake/project_common.cmake @@ -128,7 +128,14 @@ macro (demo_app dir targ) set(src_files ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/${targ}.c) endif() - add_executable(${bin_name} ${ARGV2} ${src_files}) + if(CMAKE_SYSTEM_NAME MATCHES "^Retro") + set(bin_name ${targ}) + add_application(${bin_name} ${src_files} ${PDC_MAC_RESOURCES}) + add_dependencies(${bin_name} ${PROJECT_NAME}_resources) + else() + add_executable(${bin_name} ${ARGV2} ${src_files}) + set_target_properties(${bin_name} PROPERTIES OUTPUT_NAME ${targ}) + endif() target_link_libraries(${bin_name} PRIVATE ${PDCURSE_PROJ} ${EXTRA_LIBS}) if((${PROJECT_NAME} STREQUAL "wincon") OR (${PROJECT_NAME} STREQUAL "wingui") OR (${PROJECT_NAME} STREQUAL "vt")) @@ -136,7 +143,6 @@ macro (demo_app dir targ) endif() add_dependencies(${bin_name} ${PDCURSE_PROJ}) - set_target_properties(${bin_name} PROPERTIES OUTPUT_NAME ${targ}) install(TARGETS ${bin_name} RUNTIME DESTINATION ${PDCURSES_DIST}/bin/${PROJECT_NAME} COMPONENT applications) endmacro () diff --git a/curses.h b/curses.h index 3049ee89..810bb744 100644 --- a/curses.h +++ b/curses.h @@ -179,7 +179,8 @@ enum PDC_port PDC_PORT_LINUX_FB = 10, PDC_PORT_OPENGL = 11, PDC_PORT_OS2GUI = 12, - PDC_PORT_SDL3 = 13 + PDC_PORT_SDL3 = 13, + PDC_PORT_MAC = 14 }; /* Use this structure with PDC_get_version() for run-time info about the diff --git a/demos/testcurs.c b/demos/testcurs.c index bfb8ba8b..0a360e8b 100644 --- a/demos/testcurs.c +++ b/demos/testcurs.c @@ -1918,6 +1918,7 @@ void colorTest(WINDOW *win) #if HAVE_WIDE void wideTest(WINDOW *win) { + wint_t input[513]; wchar_t tmp[513]; size_t i; @@ -1930,7 +1931,10 @@ void wideTest(WINDOW *win) echo(); - get_wstr((wint_t *)tmp); + get_wstr(input); + for (i = 0; input[i]; i++) + tmp[i] = (wchar_t)input[i]; + tmp[i] = 0; addstr("\n\n String:\n\n "); addwstr(tmp); addstr("\n\n\n Hex:\n\n "); diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt new file mode 100644 index 00000000..b5325bfd --- /dev/null +++ b/mac/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.11) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING "Choose the type of build, options are: Debug, Release, or MinSizeRel." FORCE) + message(STATUS "No build type specified, defaulting to MinSizeRel.") +endif() + +PROJECT(mac VERSION "${PROJECT_VERSION}" LANGUAGES C) + +INCLUDE(project_common) + +target_include_directories(${PDCURSE_PROJ} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../common) + +if(CMAKE_SYSTEM_NAME MATCHES "^Retro") + set(PDC_MAC_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/pdcurses.rsrc.bin) + set(PDC_MAC_REZ_INCLUDES ${REZ_INCLUDE_PATH}) + list(TRANSFORM PDC_MAC_REZ_INCLUDES PREPEND -I) + add_custom_command(OUTPUT ${PDC_MAC_RESOURCES} + COMMAND ${REZ} ${CMAKE_CURRENT_SOURCE_DIR}/pdcurses.r ${PDC_MAC_REZ_INCLUDES} -o ${PDC_MAC_RESOURCES} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pdcurses.r) + add_custom_target(${PROJECT_NAME}_resources DEPENDS ${PDC_MAC_RESOURCES}) +endif() + +demo_app(../demos calendar) +demo_app(../demos firework) +demo_app(../demos init_col) +demo_app(../demos mbrot) +demo_app(../demos newtest) +demo_app(../demos ozdemo) +demo_app(../demos picsview) +demo_app(../demos ptest) +demo_app(../demos rain) +demo_app(../demos speed) +demo_app(../demos test_pan) +demo_app(../demos testcurs) +demo_app(../demos version) +demo_app(../demos widetest) +demo_app(../demos worm) +demo_app(../demos xmas) + +SET(CPACK_COMPONENTS_ALL applications) diff --git a/mac/README.md b/mac/README.md new file mode 100644 index 00000000..5342ab57 --- /dev/null +++ b/mac/README.md @@ -0,0 +1,92 @@ +PDCursesMod for Macintosh Classic/Carbon +========================================= + +This directory contains PDCursesMod source code files +specific to the Macintosh classic/carbon graphics mode +(Macintosh classic has no command line, so this is the only +mode there). This will work with System 7 and early OSX with +CarbonLib on either 68k or PowerPC. + +Building +-------- + +- You can cross-compile with Retro68 using CMake. This is + the main way to do it as you get a modern compiler with + modern optimizations. Some Linux distros have a package + for Retro68, but for those that don't there are a couple + options: + + 1) The main Retro68 repo at https://github.com/autc04/Retro68/ + 2) Matthewdeaves's fork at https://github.com/matthewdeaves/Retro68 which includes a more hands-free setup script + +- A CodeWarrior 8 file is included for native compilation + and debugging. The non-CMake options include: + + pdcursescw8mac.sit - Macintosh CodeWarrior 8 (non-Pro) 68k project file + +- Use Stuffit Expander to extract the native Macintosh CodeWarrior 8 + project. It is compressed to preserve its resources. + +- The CodeWarrior project files include only the library itself. + If you want compile a demo, test, or your own application, + either add it as a target to the project or make your own + project file and add PDCursesMod as a library. + +- If making an application include pdcurses.r or your own resource file. + +- As mentioned above this port supports several architectures: + + 68k - Builds for early Macintosh Classic non-PowerPC + PowerPC - Builds for Macintosh Classic PowerPC + FAT - Builds for Macintosh Classic 68k/PowerPC hybrid + Carbon - Builds for Macintosh Carbon 1.0 + +- Carbon requires System 8+ with the CarbonLib extension on + Macintosh Classic or early PowerPC-based Mac OSX. + +Retro68 CMake Information +------------------------------ + +Using Retro68 with CMake generally requires its own cmake +toolchain file. Typically you'd have this already set up. For +example if Retro68 was setup in /home/user/Retro68-build your +toolchain would look something like: + + if(RETROPOWERPCOPT OR RETROCARBONOPT) + set(CMAKE_AR /home/user/Retro68-build/toolchain/bin/powerpc-apple-macos-ar) + set(CMAKE_RANLIB /home/user/Retro68-build/toolchain/bin/powerpc-apple-macos-ranlib) + set(CMAKE_LINKER /home/user/Retro68-build/toolchain/bin/powerpc-apple-macos-ld) + set(CMAKE_C_COMPILER /home/user/Retro68-build/toolchain/bin/powerpc-apple-macos-gcc) + set(CMAKE_CXX_COMPILER /home/user/Retro68-build/toolchain/bin/powerpc-apple-macos-g++) + if(RETROCARBONOPT) + set(CMAKE_EXE_LINKER_FLAGS_INIT "-carbon") + add_definitions(-DTARGET_API_MAC_CARBON=1) + set(CMAKE_SYSTEM_NAME RetroCarbon) + else() + set(CMAKE_SYSTEM_NAME RetroPPC) + endif() + else() + set(CMAKE_AR /home/user/Retro68-build/toolchain/bin/m68k-apple-macos-ar) + set(CMAKE_RANLIB /home/user/Retro68-build/toolchain/bin/m68k-apple-macos-ranlib) + set(CMAKE_LINKER /home/user/Retro68-build/toolchain/bin/m68k-apple-macos-ld) + set(CMAKE_C_COMPILER /home/user/Retro68-build/toolchain/bin/m68k-apple-macos-gcc) + set(CMAKE_CXX_COMPILER /home/user/Retro68-build/toolchain/bin/m68k-apple-macos-g++) + set(CMAKE_SYSTEM_NAME Retro68) + endif() + + set(REZ /home/user/Retro68-build/toolchain/bin/Rez) + +Once you have that set up you'd either pass it to the commandline or +add it to the cmake files via: + + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/retro68-gcc-toolchain.cmake) + +Distribution Status +------------------- + +The files in this directory are released to the Public Domain. + +Acknowledgements +---------------- + +Structure based on the Win32 GUI port by Bill Gray. diff --git a/mac/pdcclip.c b/mac/pdcclip.c new file mode 100644 index 00000000..3c61d011 --- /dev/null +++ b/mac/pdcclip.c @@ -0,0 +1,361 @@ +#include "pdcmac.h" +#include +#include + +static const unsigned short macroman_unicode[128] = +{ + 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, + 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, + 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, + 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, + 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, + 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, + 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, + 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, + 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, + 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, + 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, + 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, + 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, + 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, + 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, + 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7 +}; + +unsigned short PDC_macroman_to_unicode(unsigned char ch) +{ + if (ch < 0x80) + return (unsigned short)ch; + return macroman_unicode[ch - 0x80]; +} + +unsigned char PDC_unicode_to_macroman(unsigned long code) +{ + int i; + + if (code < 0x80) + return (unsigned char)code; + for (i = 0; i < 128; i++) + { + if ((unsigned long)macroman_unicode[i] == code) + return (unsigned char)(i + 0x80); + } + return (unsigned char)'?'; +} + +static int utf8_encode(unsigned long code, char *out) +{ + if (code < 0x80) + { + out[0] = (char)code; + return 1; + } + if (code < 0x800) + { + out[0] = (char)(0xC0 | (code >> 6)); + out[1] = (char)(0x80 | (code & 0x3F)); + return 2; + } + if (code < 0x10000) + { + out[0] = (char)(0xE0 | (code >> 12)); + out[1] = (char)(0x80 | ((code >> 6) & 0x3F)); + out[2] = (char)(0x80 | (code & 0x3F)); + return 3; + } + out[0] = (char)(0xF0 | (code >> 18)); + out[1] = (char)(0x80 | ((code >> 12) & 0x3F)); + out[2] = (char)(0x80 | ((code >> 6) & 0x3F)); + out[3] = (char)(0x80 | (code & 0x3F)); + return 4; +} + +static unsigned long utf8_decode(const unsigned char **pp, const unsigned char *end) +{ + const unsigned char *p; + unsigned long code; + unsigned int extra; + + p = *pp; + if (p >= end) + return 0; + if (p[0] < 0x80) + { + code = p[0]; + *pp = p + 1; + return code; + } + if ((p[0] & 0xE0) == 0xC0) + { + extra = 1; + code = p[0] & 0x1F; + } + else if ((p[0] & 0xF0) == 0xE0) + { + extra = 2; + code = p[0] & 0x0F; + } + else if ((p[0] & 0xF8) == 0xF0) + { + extra = 3; + code = p[0] & 0x07; + } + else + { + *pp = p + 1; + return (unsigned long)'?'; + } + if (p + extra >= end) + { + *pp = end; + return (unsigned long)'?'; + } + while (extra) + { + p++; + extra--; + if ((p[0] & 0xC0) != 0x80) + { + *pp = p; + return (unsigned long)'?'; + } + code = (code << 6) | (p[0] & 0x3F); + } + *pp = p + 1; + return code; +} + +static int use_utf8_clipboard(void) +{ +#ifdef PDC_WIDE + return 1; +#else +#ifdef PDC_FORCE_UTF8 + return 1; +#else + return 0; +#endif +#endif +} + +static char *macroman_buffer_to_result(const char *src, long srclen, long *outlen) +{ + char *result; + long i; + long destlen; + long destpos; + + if (!use_utf8_clipboard()) + { + result = (char *)malloc((size_t)srclen + 1); + if (!result) + return NULL; + memcpy(result, src, (size_t)srclen); + result[srclen] = 0; + *outlen = srclen; + return result; + } + destlen = 0; + for (i = 0; i < srclen; i++) + { + unsigned long code; + char temp[4]; + + code = PDC_macroman_to_unicode((unsigned char)src[i]); + destlen += utf8_encode(code, temp); + } + result = (char *)malloc((size_t)destlen + 1); + if (!result) + return NULL; + destpos = 0; + for (i = 0; i < srclen; i++) + { + unsigned long code; + char temp[4]; + int n; + + code = PDC_macroman_to_unicode((unsigned char)src[i]); + n = utf8_encode(code, temp); + memcpy(result + destpos, temp, (size_t)n); + destpos += n; + } + result[destpos] = 0; + *outlen = destpos; + return result; +} + +static char *result_to_macroman(const char *src, long srclen, long *outlen) +{ + char *result; + long destpos; + + if (!use_utf8_clipboard()) + { + result = (char *)malloc((size_t)srclen + 1); + if (!result) + return NULL; + memcpy(result, src, (size_t)srclen); + result[srclen] = 0; + *outlen = srclen; + return result; + } + result = (char *)malloc((size_t)srclen + 1); + if (!result) + return NULL; + destpos = 0; + { + const unsigned char *p; + const unsigned char *end; + + p = (const unsigned char *)src; + end = p + srclen; + while (p < end) + { + unsigned long code; + + code = utf8_decode(&p, end); + result[destpos] = (char)PDC_unicode_to_macroman(code); + destpos++; + } + } + result[destpos] = 0; + *outlen = destpos; + return result; +} + +int PDC_getclipboard(char **contents, long *length) +{ + char *raw; + long rawlen; + + PDC_LOG(("PDC_getclipboard() - called\n")); + *contents = NULL; + *length = 0; +#if TARGET_API_MAC_CARBON + { + ScrapRef scrap; + Size bytecount; + OSStatus err; + + err = GetCurrentScrap(&scrap); + if (err != noErr) + return PDC_CLIP_ACCESS_ERROR; + err = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &bytecount); + if (err == noTypeErr || bytecount <= 0) + return PDC_CLIP_EMPTY; + if (err != noErr) + return PDC_CLIP_ACCESS_ERROR; + raw = (char *)malloc((size_t)bytecount + 1); + if (!raw) + return PDC_CLIP_MEMORY_ERROR; + err = GetScrapFlavorData(scrap, kScrapFlavorTypeText, &bytecount, raw); + if (err != noErr) + { + free(raw); + return PDC_CLIP_ACCESS_ERROR; + } + rawlen = (long)bytecount; + raw[rawlen] = 0; + } +#else + { + Handle datahandle; + long offset; + long scraplen; + + datahandle = NewHandle(0); + if (!datahandle) + return PDC_CLIP_MEMORY_ERROR; + scraplen = GetScrap(datahandle, kScrapFlavorTypeText, &offset); + if (scraplen <= 0) + { + DisposeHandle(datahandle); + if (scraplen == 0 || scraplen == noTypeErr) + return PDC_CLIP_EMPTY; + return PDC_CLIP_ACCESS_ERROR; + } + HLock(datahandle); + raw = (char *)malloc((size_t)scraplen + 1); + if (!raw) + { + HUnlock(datahandle); + DisposeHandle(datahandle); + return PDC_CLIP_MEMORY_ERROR; + } + BlockMoveData(*datahandle, raw, scraplen); + rawlen = scraplen; + raw[rawlen] = 0; + HUnlock(datahandle); + DisposeHandle(datahandle); + } +#endif + *contents = macroman_buffer_to_result(raw, rawlen, length); + free(raw); + if (!*contents) + return PDC_CLIP_MEMORY_ERROR; + return PDC_CLIP_SUCCESS; +} + +int PDC_setclipboard(const char *contents, long length) +{ + char *macroman; + long maclen; +#if TARGET_API_MAC_CARBON + OSStatus err; +#else + OSErr err; +#endif + + PDC_LOG(("PDC_setclipboard() - called\n")); + if (!contents) + return PDC_clearclipboard(); + macroman = result_to_macroman(contents, length, &maclen); + if (!macroman) + return PDC_CLIP_MEMORY_ERROR; +#if TARGET_API_MAC_CARBON + { + ScrapRef scrap; + + err = ClearCurrentScrap(); + if (err == noErr) + err = GetCurrentScrap(&scrap); + if (err == noErr) + err = PutScrapFlavor(scrap, kScrapFlavorTypeText, 0, maclen, macroman); + } +#else + err = ZeroScrap(); + if (err == noErr) + err = PutScrap(maclen, kScrapFlavorTypeText, macroman); +#endif + free(macroman); + if (err != noErr) + return PDC_CLIP_ACCESS_ERROR; + return PDC_CLIP_SUCCESS; +} + +int PDC_freeclipboard(char *contents) +{ + PDC_LOG(("PDC_freeclipboard() - called\n")); + if (contents) + free(contents); + return PDC_CLIP_SUCCESS; +} + +int PDC_clearclipboard(void) +{ +#if TARGET_API_MAC_CARBON + OSStatus err; +#else + OSErr err; +#endif + + PDC_LOG(("PDC_clearclipboard() - called\n")); +#if TARGET_API_MAC_CARBON + err = ClearCurrentScrap(); +#else + err = ZeroScrap(); +#endif + if (err != noErr) + return PDC_CLIP_ACCESS_ERROR; + return PDC_CLIP_SUCCESS; +} diff --git a/mac/pdcdisp.c b/mac/pdcdisp.c new file mode 100644 index 00000000..c42defac --- /dev/null +++ b/mac/pdcdisp.c @@ -0,0 +1,741 @@ +#include "pdcmac.h" +#include + +#define USE_UNICODE_ACS_CHARS 1 + +#include +#include +#include + +#ifndef PACK_RGB +#define PACK_RGB(red, green, blue) ((PACKED_RGB)(red) | ((PACKED_RGB)(green) << 8) | ((PACKED_RGB)(blue) << 16)) +#endif + +#define BOX_LIGHT 1 +#define BOX_HEAVY 2 +#define BOX_DOUBLE 3 +#define BOX_ARMS(up, down, left, right) (((up) << 6) | ((down) << 4) | ((left) << 2) | (right)) + +static void packed_to_rgb(PACKED_RGB packed, RGBColor *color) +{ + unsigned int red; + unsigned int green; + unsigned int blue; + + red = Get_RValue(packed); + green = Get_GValue(packed); + blue = Get_BValue(packed); + color->red = (unsigned short)((red << 8) | red); + color->green = (unsigned short)((green << 8) | green); + color->blue = (unsigned short)((blue << 8) | blue); +} + +static void fill_rect(Rect *cell, const RGBColor *color) +{ + RGBForeColor(color); + PaintRect(cell); +} + +static int box_arms(unsigned long ch) +{ + static const struct + { + unsigned short code; + unsigned char arms; + } box_table[] = + { + { 0x2500, BOX_ARMS(0, 0, 1, 1) }, { 0x2501, BOX_ARMS(0, 0, 2, 2) }, + { 0x2502, BOX_ARMS(1, 1, 0, 0) }, { 0x2503, BOX_ARMS(2, 2, 0, 0) }, + { 0x250C, BOX_ARMS(0, 1, 0, 1) }, { 0x250F, BOX_ARMS(0, 2, 0, 2) }, + { 0x2510, BOX_ARMS(0, 1, 1, 0) }, { 0x2513, BOX_ARMS(0, 2, 2, 0) }, + { 0x2514, BOX_ARMS(1, 0, 0, 1) }, { 0x2517, BOX_ARMS(2, 0, 0, 2) }, + { 0x2518, BOX_ARMS(1, 0, 1, 0) }, { 0x251B, BOX_ARMS(2, 0, 2, 0) }, + { 0x251C, BOX_ARMS(1, 1, 0, 1) }, { 0x2523, BOX_ARMS(2, 2, 0, 2) }, + { 0x2524, BOX_ARMS(1, 1, 1, 0) }, { 0x252B, BOX_ARMS(2, 2, 2, 0) }, + { 0x252C, BOX_ARMS(0, 1, 1, 1) }, { 0x2533, BOX_ARMS(0, 2, 2, 2) }, + { 0x2534, BOX_ARMS(1, 0, 1, 1) }, { 0x253B, BOX_ARMS(2, 0, 2, 2) }, + { 0x253C, BOX_ARMS(1, 1, 1, 1) }, { 0x254B, BOX_ARMS(2, 2, 2, 2) }, + { 0x2550, BOX_ARMS(0, 0, 3, 3) }, { 0x2551, BOX_ARMS(3, 3, 0, 0) }, + { 0x2552, BOX_ARMS(0, 1, 0, 3) }, { 0x2553, BOX_ARMS(0, 3, 0, 1) }, + { 0x2554, BOX_ARMS(0, 3, 0, 3) }, { 0x2555, BOX_ARMS(0, 1, 3, 0) }, + { 0x2556, BOX_ARMS(0, 3, 1, 0) }, { 0x2557, BOX_ARMS(0, 3, 3, 0) }, + { 0x2558, BOX_ARMS(1, 0, 0, 3) }, { 0x2559, BOX_ARMS(3, 0, 0, 1) }, + { 0x255A, BOX_ARMS(3, 0, 0, 3) }, { 0x255B, BOX_ARMS(1, 0, 3, 0) }, + { 0x255C, BOX_ARMS(3, 0, 1, 0) }, { 0x255D, BOX_ARMS(3, 0, 3, 0) }, + { 0x255E, BOX_ARMS(1, 1, 0, 3) }, { 0x255F, BOX_ARMS(3, 3, 0, 1) }, + { 0x2560, BOX_ARMS(3, 3, 0, 3) }, { 0x2561, BOX_ARMS(1, 1, 3, 0) }, + { 0x2562, BOX_ARMS(3, 3, 1, 0) }, { 0x2563, BOX_ARMS(3, 3, 3, 0) }, + { 0x2564, BOX_ARMS(0, 1, 3, 3) }, { 0x2565, BOX_ARMS(0, 3, 1, 1) }, + { 0x2566, BOX_ARMS(0, 3, 3, 3) }, { 0x2567, BOX_ARMS(1, 0, 3, 3) }, + { 0x2568, BOX_ARMS(3, 0, 1, 1) }, { 0x2569, BOX_ARMS(3, 0, 3, 3) }, + { 0x256A, BOX_ARMS(1, 1, 3, 3) }, { 0x256B, BOX_ARMS(3, 3, 1, 1) }, + { 0x256C, BOX_ARMS(3, 3, 3, 3) }, { 0x256D, BOX_ARMS(0, 1, 0, 1) }, + { 0x256E, BOX_ARMS(0, 1, 1, 0) }, { 0x256F, BOX_ARMS(1, 0, 1, 0) }, + { 0x2570, BOX_ARMS(1, 0, 0, 1) } + }; + int i; + + if (ch < 0x2500 || ch > 0x2570) + return 0; + for (i = 0; i < (int)(sizeof(box_table) / sizeof(box_table[0])); i++) + if (box_table[i].code == ch) + return box_table[i].arms; + return 0; +} + +static void box_line(int x1, int y1, int x2, int y2, int weight) +{ + if (weight == BOX_HEAVY) + PenSize(2, 2); + MoveTo(x1, y1); + LineTo(x2, y2); + PenSize(1, 1); +} + +static int box_single_end(int weight_here, int weight_opposite, int both_across, + int center, int nearline, int farline, int across_double) +{ + if (!across_double) + return center; + if (both_across && !weight_opposite) + return nearline; + if (weight_here) + return farline; + return center; +} + +static void draw_box(int arms, const Rect *cell) +{ + int up; + int down; + int left; + int right; + int midx; + int midy; + int top; + int bottom; + int leftx; + int rightx; + int vdouble; + int hdouble; + + up = (arms >> 6) & 3; + down = (arms >> 4) & 3; + left = (arms >> 2) & 3; + right = arms & 3; + midx = (cell->left + cell->right) / 2; + midy = (cell->top + cell->bottom) / 2; + top = cell->top; + bottom = cell->bottom - 1; + leftx = cell->left; + rightx = cell->right - 1; + vdouble = up == BOX_DOUBLE || down == BOX_DOUBLE; + hdouble = left == BOX_DOUBLE || right == BOX_DOUBLE; + if ((vdouble || hdouble) + && (!up || up == BOX_DOUBLE) && (!down || down == BOX_DOUBLE) + && (!left || left == BOX_DOUBLE) && (!right || right == BOX_DOUBLE)) + { + if (up) + { + box_line(midx - 1, top, midx - 1, midy - 1, BOX_LIGHT); + box_line(midx + 1, top, midx + 1, midy - 1, BOX_LIGHT); + } + else + box_line(midx - 1, midy - 1, midx + 1, midy - 1, BOX_LIGHT); + if (down) + { + box_line(midx - 1, midy + 1, midx - 1, bottom, BOX_LIGHT); + box_line(midx + 1, midy + 1, midx + 1, bottom, BOX_LIGHT); + } + else + box_line(midx - 1, midy + 1, midx + 1, midy + 1, BOX_LIGHT); + if (left) + { + box_line(leftx, midy - 1, midx - 1, midy - 1, BOX_LIGHT); + box_line(leftx, midy + 1, midx - 1, midy + 1, BOX_LIGHT); + } + else + box_line(midx - 1, midy - 1, midx - 1, midy + 1, BOX_LIGHT); + if (right) + { + box_line(midx + 1, midy - 1, rightx, midy - 1, BOX_LIGHT); + box_line(midx + 1, midy + 1, rightx, midy + 1, BOX_LIGHT); + } + else + box_line(midx + 1, midy - 1, midx + 1, midy + 1, BOX_LIGHT); + return; + } + if (up == BOX_DOUBLE || down == BOX_DOUBLE) + { + if (up) + { + box_line(midx - 1, top, midx - 1, midy, BOX_LIGHT); + box_line(midx + 1, top, midx + 1, midy, BOX_LIGHT); + } + if (down) + { + box_line(midx - 1, midy, midx - 1, bottom, BOX_LIGHT); + box_line(midx + 1, midy, midx + 1, bottom, BOX_LIGHT); + } + } + else + { + if (up) + box_line(midx, top, midx, box_single_end(up, down, left && right, + midy, midy - 1, midy + 1, hdouble), up); + if (down) + box_line(midx, box_single_end(down, up, left && right, + midy, midy + 1, midy - 1, hdouble), midx, bottom, down); + } + if (left == BOX_DOUBLE || right == BOX_DOUBLE) + { + if (left) + { + box_line(leftx, midy - 1, midx, midy - 1, BOX_LIGHT); + box_line(leftx, midy + 1, midx, midy + 1, BOX_LIGHT); + } + if (right) + { + box_line(midx, midy - 1, rightx, midy - 1, BOX_LIGHT); + box_line(midx, midy + 1, rightx, midy + 1, BOX_LIGHT); + } + } + else + { + if (left) + box_line(leftx, midy, box_single_end(left, right, up && down, + midx, midx - 1, midx + 1, vdouble), midy, left); + if (right) + box_line(box_single_end(right, left, up && down, + midx, midx + 1, midx - 1, vdouble), midy, rightx, midy, right); + } +} + +static void draw_small_pair(const Rect *cell, char first, char second) +{ + int size; + + size = PDC_font_size / 2 + 1; + TextSize(size); + MoveTo(cell->left, cell->top + size); + DrawChar(first); + if (second) + { + MoveTo(cell->right - CharWidth(second), cell->bottom - 1); + DrawChar(second); + } + TextSize(PDC_font_size); +} + +static void draw_face(const Rect *cell, int filled, const RGBColor *bg) +{ + Rect face; + Rect eye; + int diameter; + int midx; + int midy; + + diameter = cell->right - cell->left - 1; + midx = (cell->left + cell->right) / 2; + midy = (cell->top + cell->bottom) / 2; + SetRect(&face, midx - diameter / 2, midy - diameter / 2, + midx - diameter / 2 + diameter, midy - diameter / 2 + diameter); + if (filled) + { + PaintOval(&face); + RGBForeColor(bg); + } + else + FrameOval(&face); + SetRect(&eye, face.left + 2, face.top + 2, face.left + 3, face.top + 3); + PaintRect(&eye); + OffsetRect(&eye, diameter - 5, 0); + PaintRect(&eye); + MoveTo(face.left + 2, face.bottom - 3); + LineTo(face.right - 3, face.bottom - 3); +} + +static int draw_graphic(unsigned long ch, Rect *cell, const RGBColor *fg, const RGBColor *bg) +{ + int midx; + int midy; + int arms; + Rect shape; + + midx = (cell->left + cell->right) / 2; + midy = (cell->top + cell->bottom) / 2; + RGBForeColor(fg); + PenNormal(); + arms = box_arms(ch); + if (arms) + { + draw_box(arms, cell); + return 1; + } + shape = *cell; + switch (ch) + { + case 0x2588: + PaintRect(cell); + return 1; + case 0x2580: + shape.bottom = midy; + PaintRect(&shape); + return 1; + case 0x2584: + shape.top = midy; + PaintRect(&shape); + return 1; + case 0x258C: + shape.right = midx; + PaintRect(&shape); + return 1; + case 0x2590: + shape.left = midx; + PaintRect(&shape); + return 1; + case 0x2591: + case 0x2592: + case 0x2593: + { + Pattern pat; + +#if TARGET_API_MAC_CARBON + if (ch == 0x2591) + GetQDGlobalsLightGray(&pat); + else if (ch == 0x2593) + GetQDGlobalsDarkGray(&pat); + else + GetQDGlobalsGray(&pat); +#else + if (ch == 0x2591) + pat = qd.ltGray; + else if (ch == 0x2593) + pat = qd.dkGray; + else + pat = qd.gray; +#endif + PenPat(&pat); + PaintRect(cell); + PenNormal(); + } + return 1; + case 0x23BA: + case 0x23BB: + case 0x23BC: + case 0x23BD: + shape.top = cell->top + (int)(ch - 0x23BA) * (cell->bottom - cell->top - 1) / 3; + MoveTo(cell->left, shape.top); + LineTo(cell->right - 1, shape.top); + return 1; + case 0x25A0: + InsetRect(&shape, (cell->right - cell->left) / 4, (cell->bottom - cell->top) / 3); + PaintRect(&shape); + return 1; + case 0x25CB: + SetRect(&shape, cell->left + 1, midy - (cell->right - cell->left) / 2 + 1, + cell->right - 1, midy + (cell->right - cell->left) / 2 - 1); + FrameOval(&shape); + return 1; + case 0x263A: + draw_face(cell, 0, bg); + return 1; + case 0x263B: + draw_face(cell, 1, bg); + return 1; + case 0x263C: + SetRect(&shape, midx - 2, midy - 2, midx + 3, midy + 3); + FrameOval(&shape); + MoveTo(midx, midy - 5); + LineTo(midx, midy + 5); + MoveTo(cell->left, midy); + LineTo(cell->right - 1, midy); + return 1; + case 0x2310: + MoveTo(cell->right - 2, midy); + LineTo(cell->left + 1, midy); + LineTo(cell->left + 1, midy + (cell->bottom - cell->top) / 5); + return 1; + case 0x00B2: + draw_small_pair(cell, '2', 0); + return 1; + case 0x207F: + draw_small_pair(cell, 'n', 0); + return 1; + case 0x00BD: + draw_small_pair(cell, '1', '2'); + return 1; + case 0x00BC: + draw_small_pair(cell, '1', '4'); + return 1; + case 0x20A7: + draw_small_pair(cell, 'P', 't'); + return 1; + } + return 0; +} + +static unsigned char unicode_to_symbol(unsigned long ch) +{ + static const struct + { + unsigned short code; + unsigned char symbol; + } symbol_table[] = + { + { 0x2190, 0xAC }, { 0x2191, 0xAD }, + { 0x2192, 0xAE }, { 0x2193, 0xAF }, { 0x2219, 0xB7 }, { 0x2229, 0xC7 }, + { 0x2261, 0xBA }, { 0x2320, 0xF3 }, { 0x2321, 0xF5 }, { 0x25C6, 0xA8 }, + { 0x2660, 0xAA }, { 0x2663, 0xA7 }, { 0x2665, 0xA9 }, { 0x2666, 0xA8 } + }; + static const char greek_upper[] = "ABGDEZHQIKLMNXOPR STUFCYW"; + static const char greek_lower[] = "abgdezhqiklmnxoprVstufcyw"; + static const char greek_accented_upper[] = "A EHI O UW"; + static const char greek_accented_lower[] = "aehi"; + static const char greek_accented_final[] = "iuouw"; + int i; + + if (ch >= 0x0386 && ch <= 0x038F && greek_accented_upper[ch - 0x0386] != ' ') + return (unsigned char)greek_accented_upper[ch - 0x0386]; + if (ch >= 0x03AC && ch <= 0x03AF) + return (unsigned char)greek_accented_lower[ch - 0x03AC]; + if (ch >= 0x03CA && ch <= 0x03CE) + return (unsigned char)greek_accented_final[ch - 0x03CA]; + if (ch >= 0x0391 && ch <= 0x03A9 && ch != 0x03A2) + return (unsigned char)greek_upper[ch - 0x0391]; + if (ch >= 0x03B1 && ch <= 0x03C9) + return (unsigned char)greek_lower[ch - 0x03B1]; + for (i = 0; i < (int)(sizeof(symbol_table) / sizeof(symbol_table[0])); i++) + if (symbol_table[i].code == ch) + return symbol_table[i].symbol; + return 0; +} + +static void draw_symbol(unsigned char code, const Rect *cell) +{ + int cellwidth; + int width; + + cellwidth = cell->right - cell->left; + TextFont(kFontIDSymbol); + width = CharWidth(code); + if (width > cellwidth) + { + TextSize((short)(PDC_font_size * cellwidth / width)); + width = CharWidth(code); + } + MoveTo(cell->left + (cellwidth - width) / 2, cell->top + PDC_font_ascent); + DrawChar(code); + TextFont(monaco); + TextSize(PDC_font_size); +} + +static void draw_text_glyph(unsigned long ch, int unicode, const Rect *cell) +{ + unsigned char code; + + code = (unsigned char)ch; + if (unicode && ch >= 0x80) + { + code = PDC_unicode_to_macroman(ch); + if (code == '?') + { + unsigned char symbolcode; + + symbolcode = unicode_to_symbol(ch); + if (symbolcode) + { + draw_symbol(symbolcode, cell); + return; + } + } + } + if (code < 32) + code = (unsigned char)' '; + MoveTo(cell->left, cell->top + PDC_font_ascent); + DrawChar(code); +} + +#ifdef USING_COMBINING_CHARACTER_SCHEME +static unsigned char compose_macroman(unsigned long base, unsigned long mark) +{ + static const struct + { + unsigned char base; + unsigned char mark; + unsigned char macroman; + } compose_table[] = + { + { 'A', 0x08, 0x80 }, { 'A', 0x0A, 0x81 }, { 'C', 0x27, 0x82 }, { 'E', 0x01, 0x83 }, + { 'N', 0x03, 0x84 }, { 'O', 0x08, 0x85 }, { 'U', 0x08, 0x86 }, { 'a', 0x01, 0x87 }, + { 'a', 0x00, 0x88 }, { 'a', 0x02, 0x89 }, { 'a', 0x08, 0x8A }, { 'a', 0x03, 0x8B }, + { 'a', 0x0A, 0x8C }, { 'c', 0x27, 0x8D }, { 'e', 0x01, 0x8E }, { 'e', 0x00, 0x8F }, + { 'e', 0x02, 0x90 }, { 'e', 0x08, 0x91 }, { 'i', 0x01, 0x92 }, { 'i', 0x00, 0x93 }, + { 'i', 0x02, 0x94 }, { 'i', 0x08, 0x95 }, { 'n', 0x03, 0x96 }, { 'o', 0x01, 0x97 }, + { 'o', 0x00, 0x98 }, { 'o', 0x02, 0x99 }, { 'o', 0x08, 0x9A }, { 'o', 0x03, 0x9B }, + { 'u', 0x01, 0x9C }, { 'u', 0x00, 0x9D }, { 'u', 0x02, 0x9E }, { 'u', 0x08, 0x9F }, + { 'A', 0x00, 0xCB }, { 'A', 0x03, 0xCC }, { 'O', 0x03, 0xCD }, { 'y', 0x08, 0xD8 }, + { 'Y', 0x08, 0xD9 }, { 'A', 0x02, 0xE5 }, { 'E', 0x02, 0xE6 }, { 'A', 0x01, 0xE7 }, + { 'E', 0x08, 0xE8 }, { 'E', 0x00, 0xE9 }, { 'I', 0x01, 0xEA }, { 'I', 0x02, 0xEB }, + { 'I', 0x08, 0xEC }, { 'I', 0x00, 0xED }, { 'O', 0x01, 0xEE }, { 'O', 0x02, 0xEF }, + { 'O', 0x00, 0xF1 }, { 'U', 0x01, 0xF2 }, { 'U', 0x02, 0xF3 }, { 'U', 0x00, 0xF4 } + }; + int i; + + if (base > 0x7F || mark < 0x300 || mark > 0x327) + return 0; + for (i = 0; i < (int)(sizeof(compose_table) / sizeof(compose_table[0])); i++) + if (compose_table[i].base == base && compose_table[i].mark == mark - 0x300) + return compose_table[i].macroman; + return 0; +} + +static unsigned char combining_accent(unsigned long mark) +{ + switch (mark) + { + case 0x300: + return 0x60; + case 0x301: + return 0xAB; + case 0x302: + return 0xF6; + case 0x303: + return 0xF7; + case 0x304: + return 0xF8; + case 0x306: + return 0xF9; + case 0x307: + return 0xFA; + case 0x308: + return 0xAC; + case 0x30A: + return 0xFB; + case 0x30B: + return 0xFD; + case 0x30C: + return 0xFF; + case 0x327: + return 0xFC; + case 0x328: + return 0xFE; + } + return 0; +} +#endif + +static void draw_cursor_shape(Rect *cell, const RGBColor *fg) +{ + int style; + Rect bar; + + style = SP->drawing_cursor; + RGBForeColor(fg); + bar = *cell; + if (style == 2) + { + InvertRect(&bar); + return; + } + if (style == 1) + { + bar.top = bar.bottom - PDC_font_height / 5; + if (bar.top < cell->top) + bar.top = cell->top; + PaintRect(&bar); + } + else if (style == 5) + { + bar.top = (cell->top + cell->bottom) / 2; + PaintRect(&bar); + } + else if (style == 3) + { + FrameRect(&bar); + } + else if (style == 4) + { + MoveTo(cell->left + 1, cell->top); + LineTo(cell->left + 1, cell->bottom - 1); + } +} + +void PDC_mac_default_background(RGBColor *color) +{ + PACKED_RGB fgpacked; + PACKED_RGB bgpacked; + + bgpacked = PACK_RGB(0, 0, 0); + if (SP && SP->pairs_allocated > 0) + PDC_get_rgb_values((chtype)0, &fgpacked, &bgpacked); + if (bgpacked == (PACKED_RGB)-1) + bgpacked = PACK_RGB(0, 0, 0); + packed_to_rgb(bgpacked, color); +} + +void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) +{ + int i; + Rect clipbounds; + + PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno)); + if (!srcp || len <= 0 || !PDC_window) + return; + PDC_mac_set_port(); + PDC_mac_port_bounds(&clipbounds); + TextFont(monaco); + TextSize(PDC_font_size); + for (i = 0; i < len; i++) + { + chtype cell; + unsigned long ch; + PACKED_RGB fgpacked; + PACKED_RGB bgpacked; + RGBColor fg; + RGBColor bg; + Rect r; + Style face; + attr_t sysattrs; + int unicode; +#ifdef USING_COMBINING_CHARACTER_SCHEME + cchar_t marks[4]; + int markcount; + int mark; +#endif + + cell = srcp[i]; + sysattrs = SP->termattrs; +#ifdef PDC_WIDE + unicode = 1; +#else + unicode = 0; +#endif + if (_is_altcharset(cell)) + { + ch = (unsigned long)acs_map[cell & 0x7f]; + unicode = 1; + } + else + ch = (unsigned long)(cell & A_CHARTEXT); +#ifdef USING_COMBINING_CHARACTER_SCHEME + markcount = 0; + while (ch > MAX_UNICODE) + { + cchar_t added; + + ch = (unsigned long)PDC_expand_combined_characters((cchar_t)ch, &added); + if (markcount < 4) + marks[markcount++] = added; + } + if (ch == DUMMY_CHAR_NEXT_TO_FULLWIDTH) + ch = (unsigned long)' '; + if (markcount == 1 && compose_macroman(ch, (unsigned long)marks[0])) + { + ch = (unsigned long)PDC_macroman_to_unicode(compose_macroman(ch, (unsigned long)marks[0])); + markcount = 0; + } +#endif + if ((cell & A_BLINK) && SP->blink_state && (sysattrs & A_BLINK)) + ch = (unsigned long)' '; + PDC_get_rgb_values(cell, &fgpacked, &bgpacked); + if (fgpacked == (PACKED_RGB)-1) + fgpacked = PACK_RGB(0xC0, 0xC0, 0xC0); + if (bgpacked == (PACKED_RGB)-1) + bgpacked = PACK_RGB(0, 0, 0); + packed_to_rgb(fgpacked, &fg); + packed_to_rgb(bgpacked, &bg); + PDC_mac_cell_rect(lineno, x + i, &r); + ClipRect(&r); + fill_rect(&r, &bg); + RGBForeColor(&fg); + RGBBackColor(&bg); + face = 0; + if ((cell & A_BOLD) && (sysattrs & A_BOLD)) + face |= bold; + if ((cell & A_ITALIC) && (sysattrs & A_ITALIC)) + face |= italic; + TextFace(face); + if (!unicode || !draw_graphic(ch, &r, &fg, &bg)) + { + RGBForeColor(&fg); + draw_text_glyph(ch, unicode, &r); + } +#ifdef USING_COMBINING_CHARACTER_SCHEME + for (mark = markcount - 1; mark >= 0; mark--) + if (combining_accent((unsigned long)marks[mark])) + { + MoveTo(r.left, r.top + PDC_font_ascent); + DrawChar(combining_accent((unsigned long)marks[mark])); + } +#endif + if (cell & (A_UNDERLINE | A_TOP | A_LEFT | A_RIGHT | A_STRIKEOUT)) + { + RGBColor linec; + int lineidx; + + lineidx = SP->line_color; + if (lineidx != -1) + packed_to_rgb(PDC_get_palette_entry(lineidx), &linec); + else + linec = fg; + RGBForeColor(&linec); + PenNormal(); + if (cell & A_UNDERLINE) + { + MoveTo(r.left, r.bottom - 1); + LineTo(r.right - 1, r.bottom - 1); + } + if (cell & A_TOP) + { + MoveTo(r.left, r.top); + LineTo(r.right - 1, r.top); + } + if (cell & A_STRIKEOUT) + { + int midy; + + midy = (r.top + r.bottom) / 2; + MoveTo(r.left, midy); + LineTo(r.right - 1, midy); + } + if (cell & A_LEFT) + { + MoveTo(r.left, r.top); + LineTo(r.left, r.bottom - 1); + } + if (cell & A_RIGHT) + { + MoveTo(r.right - 1, r.top); + LineTo(r.right - 1, r.bottom - 1); + } + } + if (SP->drawing_cursor) + draw_cursor_shape(&r, &fg); + ClipRect(&clipbounds); + } + TextFace(0); +#ifdef MAC_OS_X_VERSION_10_0 + { + CGrafPtr port; + + port = GetWindowPort(PDC_window); + if (port) + QDFlushPortBuffer(port, NULL); + } +#endif +} + +void PDC_doupdate(void) +{ +#ifdef MAC_OS_X_VERSION_10_0 + if (PDC_window) + { + CGrafPtr port; + + port = GetWindowPort(PDC_window); + if (port) + QDFlushPortBuffer(port, NULL); + } +#endif +} diff --git a/mac/pdcgetsc.c b/mac/pdcgetsc.c new file mode 100644 index 00000000..9bd40758 --- /dev/null +++ b/mac/pdcgetsc.c @@ -0,0 +1,19 @@ +#include "pdcmac.h" + +int PDC_get_cursor_mode(void) +{ + PDC_LOG(("PDC_get_cursor_mode() - called\n")); + return 0; +} + +int PDC_get_rows(void) +{ + PDC_LOG(("PDC_get_rows() - called\n")); + return PDC_rows; +} + +int PDC_get_columns(void) +{ + PDC_LOG(("PDC_get_columns() - called\n")); + return PDC_cols; +} diff --git a/mac/pdckbd.c b/mac/pdckbd.c new file mode 100644 index 00000000..4e0d45a1 --- /dev/null +++ b/mac/pdckbd.c @@ -0,0 +1,591 @@ +#include "pdcmac.h" +#include +#include +#include +#if defined(__MWERKS__) +#include "::common:mouse.c" +#else +#include "../common/mouse.c" +#endif + +int PDC_key_queue[PDC_KEY_QUEUE_SIZE]; +int PDC_key_queue_head = 0; +int PDC_key_queue_tail = 0; + +static int held_mouse_button = -1; +static Point last_mouse_local; +static long mouse_wait_until = 0; +static unsigned long last_event_tick = 0; +static int prev_special_key = -1; + +static const struct +{ + unsigned char keycode; + unsigned char numkeypad; + unsigned short normal; + unsigned short shifted; + unsigned short control; + unsigned short alt; +} key_table[] = +{ + { 0x7B, 0, KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT }, + { 0x7C, 0, KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT }, + { 0x7E, 0, KEY_UP, KEY_SUP, CTL_UP, ALT_UP }, + { 0x7D, 0, KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN }, + { 0x73, 0, KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME }, + { 0x77, 0, KEY_END, KEY_SEND, CTL_END, ALT_END }, + { 0x74, 0, KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP }, + { 0x79, 0, KEY_NPAGE, KEY_SNEXT, CTL_PGDN, ALT_PGDN }, + { 0x72, 0, KEY_IC, KEY_SIC, CTL_INS, ALT_INS }, + { 0x75, 0, KEY_DC, KEY_SDC, CTL_DEL, ALT_DEL }, + { 0x33, 0, 0x08, 0x08, CTL_BKSP, ALT_BKSP }, + { 0x30, 0, 0x09, KEY_BTAB, CTL_TAB, ALT_TAB }, + { 0x35, 0, 0x1B, 0x1B, 0x1B, ALT_ESC }, + { 0x24, 0, 0x0D, 0x0D, 0x0D, 0x0D }, + { 0x4C, 1, PADENTER, PADENTER, CTL_PADENTER, ALT_PADENTER }, + { 0x45, 1, PADPLUS, '+', CTL_PADPLUS, ALT_PADPLUS }, + { 0x4E, 1, PADMINUS, '-', CTL_PADMINUS, ALT_PADMINUS }, + { 0x43, 1, PADSTAR, '*', CTL_PADSTAR, ALT_PADSTAR }, + { 0x4B, 1, PADSLASH, '/', CTL_PADSLASH, ALT_PADSLASH }, + { 0x41, 1, PADSTOP, '.', CTL_PADSTOP, ALT_PADSTOP }, + { 0x52, 1, PAD0, '0', CTL_PAD0, ALT_PAD0 }, + { 0x53, 1, KEY_C1, '1', CTL_PAD1, ALT_PAD1 }, + { 0x54, 1, KEY_C2, '2', CTL_PAD2, ALT_PAD2 }, + { 0x55, 1, KEY_C3, '3', CTL_PAD3, ALT_PAD3 }, + { 0x56, 1, KEY_B1, '4', CTL_PAD4, ALT_PAD4 }, + { 0x57, 1, KEY_B2, '5', CTL_PAD5, ALT_PAD5 }, + { 0x58, 1, KEY_B3, '6', CTL_PAD6, ALT_PAD6 }, + { 0x59, 1, KEY_A1, '7', CTL_PAD7, ALT_PAD7 }, + { 0x5B, 1, KEY_A2, '8', CTL_PAD8, ALT_PAD8 }, + { 0x5C, 1, KEY_A3, '9', CTL_PAD9, ALT_PAD9 }, + { 0x47, 1, KEY_CLEAR, KEY_CLEAR, KEY_CLEAR, KEY_CLEAR }, + { 0x7A, 0, KEY_F(1), KEY_F(13), KEY_F(25), KEY_F(37) }, + { 0x78, 0, KEY_F(2), KEY_F(14), KEY_F(26), KEY_F(38) }, + { 0x63, 0, KEY_F(3), KEY_F(15), KEY_F(27), KEY_F(39) }, + { 0x76, 0, KEY_F(4), KEY_F(16), KEY_F(28), KEY_F(40) }, + { 0x60, 0, KEY_F(5), KEY_F(17), KEY_F(29), KEY_F(41) }, + { 0x61, 0, KEY_F(6), KEY_F(18), KEY_F(30), KEY_F(42) }, + { 0x62, 0, KEY_F(7), KEY_F(19), KEY_F(31), KEY_F(43) }, + { 0x64, 0, KEY_F(8), KEY_F(20), KEY_F(32), KEY_F(44) }, + { 0x65, 0, KEY_F(9), KEY_F(21), KEY_F(33), KEY_F(45) }, + { 0x6D, 0, KEY_F(10), KEY_F(22), KEY_F(34), KEY_F(46) }, + { 0x67, 0, KEY_F(11), KEY_F(23), KEY_F(35), KEY_F(47) }, + { 0x6F, 0, KEY_F(12), KEY_F(24), KEY_F(36), KEY_F(48) }, + { 0x69, 0, KEY_F(13), KEY_F(25), KEY_F(37), KEY_F(49) }, + { 0x6B, 0, KEY_F(14), KEY_F(26), KEY_F(38), KEY_F(50) }, + { 0x71, 0, KEY_F(15), KEY_F(27), KEY_F(39), KEY_F(51) }, + { 0, 0, 0, 0, 0, 0 } +}; + +void PDC_mac_add_key(int key) +{ + int next; + + if (!key) + return; + next = PDC_key_queue_tail + 1; + if (next >= PDC_KEY_QUEUE_SIZE) + next = 0; + if (next == PDC_key_queue_head) + return; + if (key == KEY_RESIZE) + { + int i; + + i = PDC_key_queue_head; + while (i != PDC_key_queue_tail) + { + if (PDC_key_queue[i] == KEY_RESIZE) + return; + i++; + if (i >= PDC_KEY_QUEUE_SIZE) + i = 0; + } + if (SP) + SP->resized = TRUE; + } + PDC_key_queue[PDC_key_queue_tail] = key; + PDC_key_queue_tail = next; +} + +static int queue_has_key(void) +{ + if (PDC_key_queue_head != PDC_key_queue_tail) + return 1; + return 0; +} + +static int pop_key(void) +{ + int key; + + if (PDC_key_queue_head == PDC_key_queue_tail) + return -1; + key = PDC_key_queue[PDC_key_queue_head]; + PDC_key_queue_head++; + if (PDC_key_queue_head >= PDC_KEY_QUEUE_SIZE) + PDC_key_queue_head = 0; + if (key == KEY_MOUSE) + _get_mouse_event(&SP->mouse_status); + return key; +} + +static unsigned long modifiers_from_event(const EventRecord *event) +{ + unsigned long mods; + + mods = 0; + if (event->modifiers & shiftKey) + mods |= PDC_KEY_MODIFIER_SHIFT; + if (event->modifiers & controlKey) + mods |= PDC_KEY_MODIFIER_CONTROL; + if (event->modifiers & optionKey) + mods |= PDC_KEY_MODIFIER_ALT; + if (event->modifiers & cmdKey) + mods |= PDC_KEY_MODIFIER_SUPER; + if (event->modifiers & alphaLock) + mods |= PDC_KEY_MODIFIER_CAPSLOCK; + return mods; +} + +static int mouse_modifs(const EventRecord *event) +{ + int mods; + + mods = 0; + if (event->modifiers & shiftKey) + mods |= BUTTON_SHIFT; + if (event->modifiers & controlKey) + mods |= BUTTON_CONTROL; + if (event->modifiers & optionKey) + mods |= BUTTON_ALT; + return mods; +} + +static int mouse_button_from_event(const EventRecord *event) +{ + if (event->modifiers & controlKey) + return 2; + if (event->modifiers & optionKey) + return 1; + return 0; +} + +static void local_mouse(const EventRecord *event, Point *local) +{ + *local = event->where; + PDC_mac_set_port(); + GlobalToLocal(local); +} + +static void announce_mouse_events(void) +{ + int announced; + int i; + + mouse_wait_until = 0; + announced = 0; + for (i = PDC_key_queue_head; i != PDC_key_queue_tail; ) + { + if (PDC_key_queue[i] == KEY_MOUSE) + announced++; + i++; + if (i >= PDC_KEY_QUEUE_SIZE) + i = 0; + } + while (announced < _mlist_count) + { + PDC_mac_add_key(KEY_MOUSE); + announced++; + } +} + +static void check_mouse_wait(void) +{ + if (mouse_wait_until && PDC_millisecs() - mouse_wait_until >= 0) + announce_mouse_events(); +} + +static void mouse_cell(const Point *local, int *x, int *y) +{ + *x = local->h / PDC_font_width; + *y = local->v / PDC_font_height; + if (*x < 0) + *x = 0; + if (*y < 0) + *y = 0; + if (SP && *x >= SP->cols) + *x = SP->cols - 1; + if (SP && *y >= SP->lines) + *y = SP->lines - 1; +} + +static void queue_mouse(int button, int event_type, const EventRecord *event) +{ + Point local; + int x; + int y; + + local_mouse(event, &local); + last_mouse_local = local; + mouse_cell(&local, &x, &y); + if (_add_raw_mouse_event(button, event_type, mouse_modifs(event), x, y) + && SP->mouse_wait > 0) + mouse_wait_until = PDC_millisecs() + SP->mouse_wait; + else + announce_mouse_events(); +} + +static int lookup_special(unsigned char keycode, unsigned long modifiers) +{ + int i; + + for (i = 0; key_table[i].normal; i++) + { + if (key_table[i].keycode != keycode) + continue; + if (modifiers & PDC_KEY_MODIFIER_SHIFT) + return key_table[i].shifted; + if (modifiers & PDC_KEY_MODIFIER_CONTROL) + return key_table[i].control; + if (modifiers & PDC_KEY_MODIFIER_ALT) + return key_table[i].alt; + return key_table[i].normal; + } + return 0; +} + +static int translate_key(const EventRecord *event) +{ + unsigned char keycode; + unsigned char charcode; + unsigned long modifiers; + int key; + + keycode = (unsigned char)((event->message & keyCodeMask) >> 8); + charcode = (unsigned char)(event->message & charCodeMask); + modifiers = modifiers_from_event(event); + SP->key_modifiers = modifiers; + if (event->what == autoKey) + SP->key_modifiers |= PDC_KEY_MODIFIER_REPEAT; + if ((event->modifiers & cmdKey) && charcode == 'q') + { + key = PDC_get_function_key(FUNCTION_KEY_SHUT_DOWN); + if (!key) + exit(0); + return key; + } + if ((event->modifiers & cmdKey) && charcode == 'c') + { + key = PDC_get_function_key(FUNCTION_KEY_COPY); + if (key) + return key; + return 3; + } + if ((event->modifiers & cmdKey) && charcode == 'v') + { + key = PDC_get_function_key(FUNCTION_KEY_PASTE); + if (key) + return key; + return 22; + } + if ((event->modifiers & cmdKey) && (charcode == '+' || charcode == '=')) + { + key = PDC_get_function_key(FUNCTION_KEY_ENLARGE_FONT); + if (key) + return key; + PDC_font_size += 2; + if (PDC_font_size > 48) + PDC_font_size = 48; + PDC_mac_apply_font(); + PDC_mac_adjust_cells(PDC_cols, PDC_rows, 1); + return -1; + } + if ((event->modifiers & cmdKey) && charcode == '-') + { + key = PDC_get_function_key(FUNCTION_KEY_SHRINK_FONT); + if (key) + return key; + PDC_font_size -= 2; + if (PDC_font_size < 6) + PDC_font_size = 6; + PDC_mac_apply_font(); + PDC_mac_adjust_cells(PDC_cols, PDC_rows, 1); + return -1; + } + key = lookup_special(keycode, modifiers); + if (key) + return key; + if (event->modifiers & cmdKey) + return -1; + if (charcode >= 32) + { +#ifdef PDC_WIDE + return (int)PDC_macroman_to_unicode(charcode); +#else + return (int)charcode; +#endif + } + if (charcode > 0) + return (int)charcode; + return -1; +} + +static void handle_key(EventRecord *event) +{ + int key; + + if (event->modifiers & cmdKey) + { + long menuresult; + + menuresult = MenuKey((short)(event->message & charCodeMask)); + if (HiWord(menuresult)) + { + PDC_mac_handle_menu(menuresult); + return; + } + } + if (event->what == keyUp) + { + unsigned char keycode; + + keycode = (unsigned char)((event->message & keyCodeMask) >> 8); + if (SP && SP->return_key_modifiers) + { + if (keycode == 0x38 || keycode == 0x3C) + PDC_mac_add_key(KEY_SHIFT_L); + else if (keycode == 0x3B || keycode == 0x3E) + PDC_mac_add_key(KEY_CONTROL_L); + else if (keycode == 0x3A || keycode == 0x3D) + PDC_mac_add_key(KEY_ALT_L); + } + prev_special_key = -1; + return; + } + key = translate_key(event); + if (key == 3 && SP && !SP->raw_inp) + exit(0); + if (key > 0 && key == PDC_get_function_key(FUNCTION_KEY_ABORT)) + exit(-1); + if (key > 0) + { + if (prev_special_key == key) + SP->key_modifiers |= PDC_KEY_MODIFIER_REPEAT; + prev_special_key = key; + PDC_mac_add_key(key); + } +} + +static void handle_content_click(EventRecord *event, int pressed) +{ + int button; + + if (pressed) + { + held_mouse_button = mouse_button_from_event(event); + queue_mouse(held_mouse_button, BUTTON_PRESSED, event); + } + else if (held_mouse_button >= 0) + { + button = held_mouse_button; + held_mouse_button = -1; + queue_mouse(button, BUTTON_RELEASED, event); + } +} + +static void handle_mouse_moved(EventRecord *event) +{ + Point local; + int button; + int x; + int y; + + if (!SP || !SP->_trap_mbe) + { + PDC_mac_reset_mouse_rgn(); + return; + } + local_mouse(event, &local); + if (local.h == last_mouse_local.h && local.v == last_mouse_local.v) + { + PDC_mac_reset_mouse_rgn(); + return; + } + last_mouse_local = local; + mouse_cell(&local, &x, &y); + button = 0; + if (held_mouse_button >= 0) + button = held_mouse_button; + _add_raw_mouse_event(button, BUTTON_MOVED, mouse_modifs(event), x, y); + if (!mouse_wait_until) + announce_mouse_events(); + PDC_mac_reset_mouse_rgn(); +} + +static void dispatch_event(EventRecord *event) +{ + WindowPtr which; + short part; + + switch (event->what) + { + case mouseDown: + part = FindWindow(event->where, &which); + if (part == inMenuBar) + { + PDC_mac_handle_menu(MenuSelect(event->where)); + break; + } +#if !TARGET_API_MAC_CARBON + if (part == inSysWindow) + { + SystemClick(event, which); + break; + } +#endif + if (which != PDC_window) + { + if (which) + SelectWindow(which); + break; + } + if (part == inDrag) + PDC_mac_drag(event); + else if (part == inGrow) + PDC_mac_grow(event); + else if (part == inGoAway) + PDC_mac_goaway(event); + else if (part == inZoomIn || part == inZoomOut) + PDC_mac_zoom(event, part); + else if (part == inContent) + { + SelectWindow(PDC_window); + handle_content_click(event, 1); + } + break; + case mouseUp: + handle_content_click(event, 0); + break; + case keyDown: + case autoKey: + case keyUp: + handle_key(event); + break; + case updateEvt: + if ((WindowPtr)event->message == PDC_window) + PDC_mac_redraw(); + break; + case activateEvt: + if ((WindowPtr)event->message == PDC_window) + { + PDC_mac_set_port(); + DrawGrowIcon(PDC_window); + } + break; + case osEvt: + { + unsigned char kind; + + kind = (unsigned char)((event->message >> 24) & 0xFF); + if (kind == mouseMovedMessage) + handle_mouse_moved(event); + else if (kind == suspendResumeMessage) + { +#if !TARGET_API_MAC_CARBON + if (event->message & resumeFlag) + LoadScrap(); + else + UnloadScrap(); +#endif + } + } + break; + case kHighLevelEvent: + AEProcessAppleEvent(event); + break; + default: + break; + } +} + +void PDC_mac_process_events(int sleepticks) +{ + EventRecord event; + Boolean got; + RgnHandle rgn; + + rgn = PDC_mouse_rgn; + got = WaitNextEvent(everyEvent, &event, sleepticks, rgn); + if (got) + dispatch_event(&event); + while (EventAvail(everyEvent, &event)) + { + got = WaitNextEvent(everyEvent, &event, 0, rgn); + if (!got) + break; + dispatch_event(&event); + } +} + +void PDC_set_keyboard_binary(bool on) +{ + INTENTIONALLY_UNUSED_PARAMETER(on); + PDC_LOG(("PDC_set_keyboard_binary() - called\n")); +} + +bool PDC_check_key(void) +{ + unsigned long tick; + + PDC_check_for_blinking(); + tick = TickCount(); + if (tick != last_event_tick) + { + last_event_tick = tick; + PDC_mac_process_events(0); + } + check_mouse_wait(); + if (queue_has_key()) + return TRUE; + return FALSE; +} + +int PDC_get_key(void) +{ + int key; + + if (!queue_has_key()) + PDC_mac_process_events(GetCaretTime()); + check_mouse_wait(); + key = pop_key(); + return key; +} + +void PDC_flushinp(void) +{ + PDC_LOG(("PDC_flushinp() - called\n")); + PDC_key_queue_head = 0; + PDC_key_queue_tail = 0; + mouse_wait_until = 0; + held_mouse_button = -1; + while (_get_mouse_event(&SP->mouse_status)) + ; + FlushEvents(keyDownMask | keyUpMask | autoKeyMask | mDownMask | mUpMask, 0); +} + +bool PDC_has_mouse(void) +{ + return TRUE; +} + +int PDC_mouse_set(void) +{ + PDC_mac_reset_mouse_rgn(); + return OK; +} + +int PDC_modifiers_set(void) +{ + return OK; +} diff --git a/mac/pdcmac.h b/mac/pdcmac.h new file mode 100644 index 00000000..b9acdbe8 --- /dev/null +++ b/mac/pdcmac.h @@ -0,0 +1,155 @@ +#ifndef PDC_MAC_H +#define PDC_MAC_H 1 + +#if !defined(TARGET_API_MAC_CARBON) && defined(TARGET_CARBON) +# define TARGET_API_MAC_CARBON TARGET_CARBON +#endif + +#define erase PDC_mac_qd_erase /* CW8 non-Pro has erase as an enum */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef erase + +#undef MOUSE_MOVED +#include + +#ifndef kScrapFlavorTypeText +#define kScrapFlavorTypeText 'TEXT' +#endif + +#define PDC_MAC_GROW_MARGIN 15 + +#ifndef zoomDocProc +#define zoomDocProc 8 +#endif + +#if !defined(NewAEEventHandlerUPP) && defined(NewAEEventHandlerProc) +#define NewAEEventHandlerUPP NewAEEventHandlerProc +#endif + +#ifndef kFontIDSymbol +#define kFontIDSymbol 23 +#endif + +#ifndef monaco +#define monaco 4 +#endif + +#ifndef bold +#define bold 1 +#endif + +#ifndef italic +#define italic 2 +#endif + +#ifndef everyEvent +#define everyEvent 0xFFFF +#endif + +#ifndef mouseMovedMessage +#define mouseMovedMessage 0xFA +#endif + +#ifndef suspendResumeMessage +#define suspendResumeMessage 1 +#endif + +#ifndef resumeFlag +#define resumeFlag 1 +#endif + +#ifndef kHighLevelEvent +#define kHighLevelEvent 23 +#endif + +#ifndef gestaltAppleEventsPresent +#define gestaltAppleEventsPresent 0 +#endif + +#ifndef noTypeErr +#define noTypeErr -204 +#endif + +#ifndef memFullErr +#define memFullErr -108 +#endif + +#ifndef charCodeMask +#define charCodeMask 0x000000FF +#endif + +#ifndef keyCodeMask +#define keyCodeMask 0x0000FF00 +#endif + +#ifndef activeFlag +#define activeFlag 0x0001 +#endif + +#define PDC_KEY_QUEUE_SIZE 64 + +extern WindowPtr PDC_window; +extern int PDC_rows; +extern int PDC_cols; +extern int PDC_font_width; +extern int PDC_font_height; +extern int PDC_font_ascent; +extern int PDC_font_size; +extern int PDC_key_queue[PDC_KEY_QUEUE_SIZE]; +extern int PDC_key_queue_head; +extern int PDC_key_queue_tail; +extern RgnHandle PDC_mouse_rgn; +extern int PDC_min_lines; +extern int PDC_max_lines; +extern int PDC_min_cols; +extern int PDC_max_cols; + +#define PDC_MENU_APPLE 128 +#define PDC_MENU_FILE 129 +#define PDC_MENU_EDIT 130 +#define PDC_ITEM_QUIT 1 +#define PDC_ITEM_CUT 1 +#define PDC_ITEM_COPY 2 +#define PDC_ITEM_PASTE 3 +#define PDC_ITEM_CLEAR 4 + +void PDC_mac_set_port(void); +void PDC_mac_port_bounds(Rect *bounds); +void PDC_mac_invalidate(const Rect *bounds); +void PDC_mac_invalidate_all(void); +void PDC_mac_cell_rect(int row, int col, Rect *cell); +void PDC_mac_add_key(int key); +void PDC_mac_process_events(int sleepticks); +void PDC_mac_apply_font(void); +void PDC_mac_reset_mouse_rgn(void); +void PDC_mac_drag(EventRecord *event); +void PDC_mac_grow(EventRecord *event); +void PDC_mac_zoom(EventRecord *event, short part); +void PDC_mac_goaway(EventRecord *event); +void PDC_mac_redraw(void); +void PDC_mac_handle_menu(long menuresult); +void PDC_mac_adjust_size(int pixelwidth, int pixelheight, int queue_resize); +void PDC_mac_adjust_cells(int cols, int rows, int queue_resize); +void PDC_mac_default_background(RGBColor *color); +unsigned short PDC_macroman_to_unicode(unsigned char ch); +unsigned char PDC_unicode_to_macroman(unsigned long code); + +void PDC_check_for_blinking(void); + +#endif diff --git a/mac/pdcscrn.c b/mac/pdcscrn.c new file mode 100644 index 00000000..9517cbf2 --- /dev/null +++ b/mac/pdcscrn.c @@ -0,0 +1,604 @@ +#include "pdcmac.h" +#include +#include +#include +#include + +#if UNIVERSAL_INTERFACES_VERSION >= 0x0340 + #define AEEVENTCBPARAM3 long +#else + #define AEEVENTCBPARAM3 UInt32 +#endif + +WindowPtr PDC_window = NULL; +int PDC_rows = 25; +int PDC_cols = 80; +int PDC_font_width = 6; +int PDC_font_height = 12; +int PDC_font_ascent = 9; +int PDC_font_size = 12; +RgnHandle PDC_mouse_rgn = NULL; +int PDC_min_lines = 2; +int PDC_max_lines = 200; +int PDC_min_cols = 2; +int PDC_max_cols = 300; + +static int toolbox_ready = 0; +static int initial_rows = 0; +static int initial_cols = 0; +static MenuHandle apple_menu; +static MenuHandle file_menu; +static MenuHandle edit_menu; + +static void c_to_pstr(const char *src, Str255 dst) +{ + unsigned int length; + unsigned int i; + + length = 0; + while (src[length] != 0 && length < 255) + length++; + dst[0] = (unsigned char)length; + for (i = 0; i < length; i++) + dst[i + 1] = (unsigned char)src[i]; +} + +void PDC_mac_set_port(void) +{ + if (!PDC_window) + return; +#if TARGET_API_MAC_CARBON + SetPortWindowPort(PDC_window); +#else + SetPort((GrafPtr)PDC_window); +#endif +} + +void PDC_mac_port_bounds(Rect *bounds) +{ +#if TARGET_API_MAC_CARBON || ACCESSOR_CALLS_ARE_FUNCTIONS + GetWindowPortBounds(PDC_window, bounds); +#else + *bounds = PDC_window->portRect; +#endif +} + +void PDC_mac_invalidate(const Rect *bounds) +{ + PDC_mac_set_port(); +#if TARGET_API_MAC_CARBON + InvalWindowRect(PDC_window, (Rect *)bounds); +#else + InvalRect((Rect *)bounds); +#endif +} + +void PDC_mac_invalidate_all(void) +{ + Rect bounds; + + PDC_mac_port_bounds(&bounds); + PDC_mac_invalidate(&bounds); +} + +void PDC_mac_cell_rect(int row, int col, Rect *cell) +{ + cell->left = (short)(col * PDC_font_width); + cell->top = (short)(row * PDC_font_height); + cell->right = (short)(cell->left + PDC_font_width); + cell->bottom = (short)(cell->top + PDC_font_height); +} + +void PDC_mac_reset_mouse_rgn(void) +{ + Point pt; + Rect r; + + if (!PDC_mouse_rgn) + return; +#if TARGET_API_MAC_CARBON + GetGlobalMouse(&pt); +#else + GetMouse(&pt); + PDC_mac_set_port(); + LocalToGlobal(&pt); +#endif + SetRect(&r, pt.h, pt.v, pt.h + 1, pt.v + 1); + RectRgn(PDC_mouse_rgn, &r); +} + +void PDC_mac_apply_font(void) +{ + FontInfo info; + + PDC_mac_set_port(); + TextFont(monaco); + TextFace(0); + TextSize(PDC_font_size); + GetFontInfo(&info); + PDC_font_ascent = info.ascent; + PDC_font_height = info.ascent + info.descent + info.leading; + PDC_font_width = CharWidth('M'); + if (PDC_font_width < 1) + PDC_font_width = CharWidth('W'); + if (PDC_font_width < 1) + PDC_font_width = PDC_font_size / 2 + 1; + if (PDC_font_height < 1) + PDC_font_height = PDC_font_size + 2; +} + +static void screen_work_rect(Rect *bounds) +{ +#if TARGET_API_MAC_CARBON + BitMap screenbits; + + GetQDGlobalsScreenBits(&screenbits); + *bounds = screenbits.bounds; +#else + *bounds = qd.screenBits.bounds; +#endif + bounds->top = (short)(bounds->top + GetMBarHeight()); +} + +static void paint_margins(void) +{ + Rect bounds; + Rect strip; + RGBColor background; + + PDC_mac_set_port(); + PDC_mac_port_bounds(&bounds); + PDC_mac_default_background(&background); + RGBForeColor(&background); + strip = bounds; + strip.left = (short)(bounds.right - PDC_MAC_GROW_MARGIN); + PaintRect(&strip); + strip = bounds; + strip.top = (short)(bounds.bottom - PDC_MAC_GROW_MARGIN); + PaintRect(&strip); + DrawGrowIcon(PDC_window); +} + +void PDC_mac_adjust_size(int pixelwidth, int pixelheight, int queue_resize) +{ + int rows; + int cols; + Rect limits; + + cols = (pixelwidth - PDC_MAC_GROW_MARGIN) / PDC_font_width; + rows = (pixelheight - PDC_MAC_GROW_MARGIN) / PDC_font_height; + if (cols < PDC_min_cols) + cols = PDC_min_cols; + if (rows < PDC_min_lines) + rows = PDC_min_lines; + if (cols > PDC_max_cols) + cols = PDC_max_cols; + if (rows > PDC_max_lines) + rows = PDC_max_lines; + if (cols < 2) + cols = 2; + if (rows < 2) + rows = 2; + SizeWindow(PDC_window, (short)(cols * PDC_font_width + PDC_MAC_GROW_MARGIN), + (short)(rows * PDC_font_height + PDC_MAC_GROW_MARGIN), TRUE); + if (PDC_cols != cols || PDC_rows != rows) + { + PDC_cols = cols; + PDC_rows = rows; + if (queue_resize) + PDC_mac_add_key(KEY_RESIZE); + } + PDC_mac_port_bounds(&limits); + PDC_mac_invalidate(&limits); + if (SP) + paint_margins(); +} + +void PDC_mac_adjust_cells(int cols, int rows, int queue_resize) +{ + PDC_mac_adjust_size(cols * PDC_font_width + PDC_MAC_GROW_MARGIN, + rows * PDC_font_height + PDC_MAC_GROW_MARGIN, queue_resize); +} + +void PDC_mac_drag(EventRecord *event) +{ + Rect screen; + + screen_work_rect(&screen); + DragWindow(PDC_window, event->where, &screen); +} + +void PDC_mac_grow(EventRecord *event) +{ + Rect limits; + long grow; + + SetRect(&limits, + (short)(PDC_min_cols * PDC_font_width + PDC_MAC_GROW_MARGIN), + (short)(PDC_min_lines * PDC_font_height + PDC_MAC_GROW_MARGIN), + (short)(PDC_max_cols * PDC_font_width + PDC_MAC_GROW_MARGIN), + (short)(PDC_max_lines * PDC_font_height + PDC_MAC_GROW_MARGIN)); + grow = GrowWindow(PDC_window, event->where, &limits); + if (grow) + PDC_mac_adjust_size(LoWord(grow), HiWord(grow), 1); +} + +void PDC_mac_zoom(EventRecord *event, short part) +{ + Rect bounds; + + if (!TrackBox(PDC_window, event->where, part)) + return; + ZoomWindow(PDC_window, part, TRUE); + PDC_mac_port_bounds(&bounds); + PDC_mac_adjust_size(bounds.right - bounds.left, bounds.bottom - bounds.top, 1); +} + +void PDC_mac_goaway(EventRecord *event) +{ + int key; + + if (!TrackGoAway(PDC_window, event->where)) + return; + key = PDC_get_function_key(FUNCTION_KEY_SHUT_DOWN); + if (!key) + exit(0); + PDC_mac_add_key(key); +} + +void PDC_mac_redraw(void) +{ + Rect bounds; + int y; + + BeginUpdate(PDC_window); + PDC_mac_set_port(); + PDC_mac_port_bounds(&bounds); + EraseRect(&bounds); + if (curscr && SP) + { + int cols; + + cols = SP->cols; + if (cols > PDC_cols) + cols = PDC_cols; + for (y = 0; y < SP->lines && y < PDC_rows; y++) + { + if (curscr->_y[y]) + PDC_transform_line(y, 0, cols, curscr->_y[y]); + } + paint_margins(); + } + else + DrawGrowIcon(PDC_window); + EndUpdate(PDC_window); +} + +void PDC_mac_handle_menu(long menuresult) +{ + short menuid; + short item; + int key; + + menuid = HiWord(menuresult); + item = LoWord(menuresult); + if (menuid == PDC_MENU_FILE && item == PDC_ITEM_QUIT) + { + key = PDC_get_function_key(FUNCTION_KEY_SHUT_DOWN); + if (!key) + exit(0); + PDC_mac_add_key(key); + } + else if (menuid == PDC_MENU_EDIT) + { + if (item == PDC_ITEM_COPY) + { + key = PDC_get_function_key(FUNCTION_KEY_COPY); + if (!key) + key = 3; + PDC_mac_add_key(key); + } + else if (item == PDC_ITEM_PASTE) + { + key = PDC_get_function_key(FUNCTION_KEY_PASTE); + if (!key) + key = 22; + PDC_mac_add_key(key); + } + else if (item == PDC_ITEM_CLEAR) + PDC_clearclipboard(); + } +#if !TARGET_API_MAC_CARBON + else if (menuid == PDC_MENU_APPLE && item > 1) + { + Str255 name; + + GetMenuItemText(apple_menu, item, name); + OpenDeskAcc(name); + } +#endif + HiliteMenu(0); +} + +static pascal OSErr ae_quit(const AppleEvent *evt, AppleEvent *reply, + AEEVENTCBPARAM3 refcon) +{ + int key; + + INTENTIONALLY_UNUSED_PARAMETER(evt); + INTENTIONALLY_UNUSED_PARAMETER(reply); + INTENTIONALLY_UNUSED_PARAMETER(refcon); + key = PDC_get_function_key(FUNCTION_KEY_SHUT_DOWN); + if (!key) + exit(0); + PDC_mac_add_key(key); + return noErr; +} + +static void init_toolbox(void) +{ + if (toolbox_ready) + return; +#if TARGET_API_MAC_CARBON + InitCursor(); +#else + MaxApplZone(); + MoreMasters(); + MoreMasters(); + InitGraf(&qd.thePort); + InitFonts(); + FlushEvents(everyEvent, 0); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(NULL); + InitCursor(); +#endif + toolbox_ready = 1; +} + +static void init_menus(void) +{ + Str255 title; + + title[0] = 1; + title[1] = 0x14; + apple_menu = NewMenu(PDC_MENU_APPLE, title); + c_to_pstr("About PDCursesMod", title); + AppendMenu(apple_menu, title); +#if !TARGET_API_MAC_CARBON + c_to_pstr("(-", title); + AppendMenu(apple_menu, title); + AppendResMenu(apple_menu, 'DRVR'); +#endif + c_to_pstr("File", title); + file_menu = NewMenu(PDC_MENU_FILE, title); + c_to_pstr("Quit/Q", title); + AppendMenu(file_menu, title); + c_to_pstr("Edit", title); + edit_menu = NewMenu(PDC_MENU_EDIT, title); + c_to_pstr("Cut/X;Copy/C;Paste/V;Clear", title); + AppendMenu(edit_menu, title); + InsertMenu(apple_menu, 0); + InsertMenu(file_menu, 0); + InsertMenu(edit_menu, 0); + DrawMenuBar(); +} + +static void install_apple_events(void) +{ +#if TARGET_API_MAC_CARBON + AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + NewAEEventHandlerUPP(ae_quit), 0, FALSE); +#else + { + long attr; + + if (Gestalt(gestaltAppleEventsAttr, &attr) == noErr) + { + if (attr & (1L << gestaltAppleEventsPresent)) + AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + NewAEEventHandlerUPP(ae_quit), 0, FALSE); + } + } +#endif +} + +static WindowPtr create_window(void) +{ + Rect screen; + Rect bounds; + Str255 title; + int width; + int height; + int left; + int top; + WindowPtr window; + + screen_work_rect(&screen); + width = PDC_cols * PDC_font_width + PDC_MAC_GROW_MARGIN; + height = PDC_rows * PDC_font_height + PDC_MAC_GROW_MARGIN; + if (width > screen.right - screen.left - 8) + width = screen.right - screen.left - 8; + if (height > screen.bottom - screen.top - 8) + height = screen.bottom - screen.top - 8; + left = screen.left + (screen.right - screen.left - width) / 2; + top = screen.top + 16; + SetRect(&bounds, (short)left, (short)top, (short)(left + width), (short)(top + height)); + c_to_pstr("PDCursesMod", title); + window = NewCWindow(NULL, &bounds, title, FALSE, zoomDocProc, + (WindowPtr)-1L, TRUE, 0); + return window; +} + +void PDC_scr_close(void) +{ + PDC_LOG(("PDC_scr_close() - called\n")); +} + +void PDC_scr_free(void) +{ + PDC_free_palette(); + if (PDC_window) + { + DisposeWindow(PDC_window); + PDC_window = NULL; + } + if (PDC_mouse_rgn) + { + DisposeRgn(PDC_mouse_rgn); + PDC_mouse_rgn = NULL; + } +#ifdef USING_COMBINING_CHARACTER_SCHEME + PDC_expand_combined_characters(0, NULL); +#endif +} + +int PDC_scr_open(void) +{ + const char *env; + + PDC_LOG(("PDC_scr_open() - called\n")); + if (!SP) + return ERR; + if (PDC_init_palette()) + return ERR; + init_toolbox(); + env = getenv("PDC_FONT_SIZE"); + if (env) + PDC_font_size = atoi(env); + if (PDC_font_size < 6) + PDC_font_size = 12; + env = getenv("PDC_LINES"); + if (env) + PDC_rows = atoi(env); + env = getenv("PDC_COLS"); + if (env) + PDC_cols = atoi(env); + if (initial_rows > 1) + PDC_rows = initial_rows; + if (initial_cols > 1) + PDC_cols = initial_cols; + if (PDC_rows < 2) + PDC_rows = 25; + if (PDC_cols < 2) + PDC_cols = 80; + if (!PDC_window) + { + PDC_font_width = PDC_font_size / 2 + 1; + PDC_font_height = PDC_font_size + 3; + PDC_font_ascent = PDC_font_size - 2; + PDC_window = create_window(); + if (!PDC_window) + return ERR; + init_menus(); + install_apple_events(); + PDC_mouse_rgn = NewRgn(); + ShowWindow(PDC_window); + SelectWindow(PDC_window); + PDC_mac_set_port(); + PDC_mac_apply_font(); + PDC_mac_adjust_cells(PDC_cols, PDC_rows, 0); + PDC_mac_reset_mouse_rgn(); + } + SP->mouse_wait = PDC_CLICK_PERIOD; + SP->audible = TRUE; + SP->mono = FALSE; + SP->orig_attr = TRUE; + SP->orig_fore = COLOR_WHITE; + SP->orig_back = COLOR_BLACK; + SP->termattrs = A_COLOR | A_UNDERLINE | A_LEFT | A_RIGHT | A_REVERSE + | A_STRIKEOUT | A_TOP | A_BLINK | A_DIM | A_BOLD | A_ITALIC; + SP->lines = PDC_rows; + SP->cols = PDC_cols; + COLORS = 256 + (256 * 256 * 256); + PDC_reset_prog_mode(); + return OK; +} + +int PDC_resize_screen(int nlines, int ncols) +{ + if (!stdscr) + { + if (nlines > 1) + initial_rows = nlines; + if (ncols > 1) + initial_cols = ncols; + if (nlines > 1) + PDC_rows = nlines; + if (ncols > 1) + PDC_cols = ncols; + return OK; + } + if (nlines > 1 && ncols > 1) + PDC_mac_adjust_cells(ncols, nlines, 0); + return OK; +} + +void PDC_reset_prog_mode(void) +{ + PDC_LOG(("PDC_reset_prog_mode() - called.\n")); + if (PDC_window) + { + ShowWindow(PDC_window); + SelectWindow(PDC_window); + PDC_mac_set_port(); + } +} + +void PDC_reset_shell_mode(void) +{ + PDC_LOG(("PDC_reset_shell_mode() - called.\n")); +} + +void PDC_restore_screen_mode(int i) +{ + INTENTIONALLY_UNUSED_PARAMETER(i); +} + +void PDC_save_screen_mode(int i) +{ + INTENTIONALLY_UNUSED_PARAMETER(i); +} + +void PDC_set_resize_limits(const int new_min_lines, const int new_max_lines, + const int new_min_cols, const int new_max_cols) +{ + PDC_min_lines = new_min_lines; + PDC_max_lines = new_max_lines; + PDC_min_cols = new_min_cols; + PDC_max_cols = new_max_cols; + if (PDC_min_lines < 2) + PDC_min_lines = 2; + if (PDC_min_cols < 2) + PDC_min_cols = 2; +} + +bool PDC_can_change_color(void) +{ + return TRUE; +} + +int PDC_color_content(int color, int *red, int *green, int *blue) +{ + const PACKED_RGB col = PDC_get_palette_entry(color); + + *red = DIVROUND(Get_RValue(col) * 1000, 255); + *green = DIVROUND(Get_GValue(col) * 1000, 255); + *blue = DIVROUND(Get_BValue(col) * 1000, 255); + return OK; +} + +int PDC_init_color(int color, int red, int green, int blue) +{ + const PACKED_RGB new_rgb = PACK_RGB(DIVROUND(red * 255, 1000), + DIVROUND(green * 255, 1000), + DIVROUND(blue * 255, 1000)); + + if (!PDC_set_palette_entry(color, new_rgb)) + { + if (curscr) + curscr->_clear = TRUE; + } + return OK; +} diff --git a/mac/pdcsetsc.c b/mac/pdcsetsc.c new file mode 100644 index 00000000..30db5302 --- /dev/null +++ b/mac/pdcsetsc.c @@ -0,0 +1,61 @@ +#include "pdcmac.h" + +int PDC_curs_set(int visibility) +{ + int ret_vis; + + PDC_LOG(("PDC_curs_set() - called: visibility=%d\n", visibility)); + ret_vis = SP->visibility; + SP->visibility = visibility; + PDC_gotoyx(SP->cursrow, SP->curscol); + return ret_vis; +} + +void PDC_set_title(const char *title) +{ + Str255 pname; + + PDC_LOG(("PDC_set_title() - called:<%s>\n", title)); + if (!PDC_window) + return; + { + unsigned int length; + unsigned int i; + + length = 0; + while (title[length] != 0 && length < 255) + length++; + pname[0] = (unsigned char)length; + for (i = 0; i < length; i++) + pname[i + 1] = (unsigned char)title[i]; + } + SetWTitle(PDC_window, pname); +} + +static int reset_attr(attr_t attr, bool attron) +{ + attr_t prev; + + if (!SP) + return ERR; + prev = SP->termattrs; + if (attron) + SP->termattrs |= attr; + else + SP->termattrs &= ~attr; + if (prev != SP->termattrs && curscr) + curscr->_clear = TRUE; + return OK; +} + +int PDC_set_blink(bool blinkon) +{ + if (SP && SP->color_started) + COLORS = 256 + (256 * 256 * 256); + return reset_attr(A_BLINK, blinkon); +} + +int PDC_set_bold(bool boldon) +{ + return reset_attr(A_BOLD, boldon); +} diff --git a/mac/pdcurses.r b/mac/pdcurses.r new file mode 100644 index 00000000..082a369b --- /dev/null +++ b/mac/pdcurses.r @@ -0,0 +1,23 @@ +#include "Types.r" + +resource 'SIZE' (-1) +{ + reserved, + acceptSuspendResumeEvents, + reserved, + canBackground, + doesActivateOnFGSwitch, + backgroundAndForeground, + dontGetFrontClicks, + ignoreChildDiedEvents, + is32BitCompatible, + isHighLevelEventAware, + onlyLocalHLEvents, + notStationeryAware, + dontUseTextEditServices, + reserved, + reserved, + reserved, + 2048 * 1024, + 512 * 1024 +}; diff --git a/mac/pdcursescw8mac.sit b/mac/pdcursescw8mac.sit new file mode 100644 index 00000000..839fab27 Binary files /dev/null and b/mac/pdcursescw8mac.sit differ diff --git a/mac/pdcutil.c b/mac/pdcutil.c new file mode 100644 index 00000000..6025c26b --- /dev/null +++ b/mac/pdcutil.c @@ -0,0 +1,46 @@ +#include "pdcmac.h" + +void PDC_beep(void) +{ + PDC_LOG(("PDC_beep() - called\n")); + SysBeep(1); +} + +void PDC_napms(int ms) +{ + unsigned long start; + unsigned long waitticks; + unsigned long fiftieths; + unsigned long remainder; + + PDC_LOG(("PDC_napms() - called: ms=%d\n", ms)); + if (ms <= 0) + return; + /* milliseconds->TickCount() ticks calculation + to prevent overflow and be reasonably performant */ + fiftieths = (unsigned long)ms / 50UL; + remainder = ((unsigned long)ms + - ((fiftieths << 5) + (fiftieths << 4) + (fiftieths << 1))) * 3UL; + waitticks = fiftieths * 3UL; + if (remainder > 100UL) + waitticks += 3UL; + else if (remainder > 50UL) + waitticks += 2UL; + else if (remainder) + waitticks += 1UL; + start = (unsigned long)TickCount(); + PDC_check_for_blinking(); + while ((unsigned long)TickCount() - start < waitticks) + { /* PDC_mac_process_events() calls WaitNextEvent() which will yield to + other threads and avoid spinning the CPU */ + PDC_mac_process_events(1); + PDC_check_for_blinking(); + } +} + +const char *PDC_sysname(void) +{ + return "Mac"; +} + +enum PDC_port PDC_port_val = PDC_PORT_MAC; diff --git a/pdcurses/debug.c b/pdcurses/debug.c index 5e36d333..15fa8a16 100644 --- a/pdcurses/debug.c +++ b/pdcurses/debug.c @@ -56,7 +56,9 @@ debug #include #include -#include +#if !defined(macintosh) && !(defined(__MWERKS__) && (defined(__MC68K__) || defined(__POWERPC__))) + #include +#endif #include void PDC_debug(const char *fmt, ...) diff --git a/pdcurses/getch.c b/pdcurses/getch.c index a0eab2b6..68209f4b 100644 --- a/pdcurses/getch.c +++ b/pdcurses/getch.c @@ -451,7 +451,9 @@ use clock_gettime() or gettimeofday() when available. */ #endif #endif -#if defined( _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) \ +#if defined( macintosh) || (defined( __MWERKS__) && (defined( __MC68K__) || defined( __POWERPC__))) + #define HAVE_TICKCOUNT +#elif defined( _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) \ && (!defined( __MINGW32__) || defined( CLOCK_REALTIME)) /* only newer MinGW environments have clock_gettime and those have CLOCK_REALTIME as a macro */ @@ -464,7 +466,18 @@ use clock_gettime() or gettimeofday() when available. */ #define HAVE_GETTIMEOFDAY #endif -#if defined( HAVE_CLOCK_GETTIME) +#if defined( HAVE_TICKCOUNT) +#define erase PDC_mac_qd_erase +#include +#undef erase +long PDC_millisecs( void) +{ + const unsigned long ticks = (unsigned long)TickCount( ); + + return( (long)(ticks * 16UL + (ticks * 2UL) / 3UL)); +} + +#elif defined( HAVE_CLOCK_GETTIME) long PDC_millisecs( void) { struct timespec t;