home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1996 October / MACPOWER-1996-10.ISO.7z / MACPOWER-1996-10.ISO / MacPowerオリジナル / キョービのプログラマ / BigText.c < prev    next >
C/C++ Source or Header  |  1996-08-13  |  16KB  |  583 lines

  1. /*----------------------------------------------Written by T.Matsubara
  2. **********       *           *           *        *  *            * *
  3. *                *           *      ***********   *  *            *  *
  4. *           *********** *********** *         *  *********   **********
  5. *********        *         *   *      ******     *   *       *    *
  6. *       *       * *        *   *          *     *    *       *    *
  7. *       *       * *        *   *         *           *       ****  * *
  8. *********      *   *        * *     ***********   *******    *  *  * *
  9. *              *   *         *           *           *       *  *   *
  10. *             *     *       * *          *           *       *  *   * *
  11. *            *       *    **   **        *           *      * **   * **
  12. **********  *         * **       **     **      *********** *     *   *
  13.  
  14.          **                     * *
  15.          **                  *  * *    ******        *
  16.  ********     *******        *                       *
  17.         *     *     *       *****                    *
  18.         *     *     *      *    *     ********      *
  19.        *      *     *    **    *             *      *  *
  20.        *      *     *          *            *      **   *
  21.       *       *******         *            *       *  ***
  22.     **        *     *       **           **      *****   *
  23.   **                      **           **                *
  24.  
  25.  *****    *         *******                 *
  26.  *    *                *                    *
  27.  *    *  **    ****    *      ***   *   *  ***       ***
  28.  *****    *   *   *    *     *   *  *   *   *       *   *
  29.  *    *   *   *   *    *     *   *   * *    *       *
  30.  *    *   *   *   *    *     *****    *     *       *
  31.  *    *   *   *   *    *     *       * *    *       *
  32.  *    *   *   *   *    *     *   *  *   *   *       *   *
  33.  *****    *    ****    *      ***   *   *    **  *   ***
  34.                   *
  35.               *   *
  36.                ***
  37. ---------------------------------------------------------------------*/
  38.  
  39. /*------------- include non-standard header file -------------*/
  40. #include <QDOffscreen.h>
  41.  
  42. /*------------- define Dialog Item's Index Number -------------*/
  43. #define    K_QUIT            1
  44. #define    K_COPY            2
  45. #define    K_FONT            3
  46. #define    K_SIZE            4
  47. #define    K_CHAR            5
  48. #define    K_TEXT            6
  49. #define    K_RESULT        7
  50.  
  51. /*------------- define char popup menu's item number -------------*/
  52. #define K_OTHER_CHAR    6
  53. #define K_KANJI_START    7
  54.  
  55. /*------------- define Offscreen gworld size -------------*/
  56. #define K_OFF_WIDTH        512
  57. #define K_OFF_HEIGHT    120
  58.  
  59. /*------------- prototypes -------------*/
  60. /*------------- main -------------*/
  61. void main(void);
  62. /*------------- initialize -------------*/
  63. void do_init_rom(void);
  64. int do_init_appl(void);
  65. long install_apple_events_handler(void);
  66. /*------------- process apple events -------------*/
  67. pascal OSErr ae_launch(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon);
  68. pascal OSErr ae_opendoc(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon);
  69. pascal OSErr ae_print(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent,  long refCon);
  70. pascal OSErr ae_quit(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon);
  71. /*------------- event loop -------------*/
  72. void do_main_event_loop(void);
  73. /*------------- management menus -------------*/
  74. void do_menu(long menu_and_item);
  75. void get_menu_options(void);
  76. void choose_other_char(void);
  77. /*------------- Utility routines -------------*/
  78. Handle get_ditm_handle(DialogPtr xdp, short itemnum);
  79. short get_ctl_value(short itemnum);
  80. void set_ctl_value(short itemnum, short value);
  81. /*------------- draw big text -------------*/
  82. pascal void draw_user_item(DialogPtr dp, short itemnum);
  83. /*------------- create big text -------------*/
  84. void create_big_text(void);
  85. void add_one_char(char what_char);
  86. void put_big_text_into_scrap(void);
  87.  
  88. /*------------- GLOBAL VAR -------------*/
  89. Boolean        exit_program = false;
  90. MenuHandle    applemenu, filemenu, editmenu;
  91. MenuHandle    pop_font, pop_size, pop_char;
  92. AEEventHandlerUPP    upp_launch, upp_opendoc, upp_print, upp_quit;
  93. DialogPtr    dp;
  94. CGrafPtr    off;
  95. Boolean        jap_script_available;
  96. Handle        big_text_hdl;
  97. Rect        big_text_area;
  98. short        cur_font_choosed;
  99. short        cur_font_id;
  100. short        cur_size_choosed;
  101. long        cur_size;
  102. short        cur_char_choosed;
  103. Boolean        cur_char_is_kanji;
  104. short        cur_kanji_char;
  105. char        cur_ascii_char;
  106. short        kanji_space = 0x8140;
  107. short        monaco_font_id;
  108. char        other_char_is_kanji = false;
  109. char        other_ascii_char = '*';
  110. short        other_kanji_char;
  111.  
  112. /*------------- Implementation -------------*/
  113. /*------------- main -------------*/
  114. void main(void)
  115. {
  116.     do_init_rom();
  117.     install_apple_events_handler();
  118.     if(do_init_appl() == 0) {
  119.         do_main_event_loop();
  120.     }
  121. }
  122.  
  123. /*------------- initialize -------------*/
  124. void do_init_rom(void)
  125. {
  126.     MaxApplZone();
  127.     MoreMasters();
  128.     InitGraf(&qd.thePort);
  129.     InitFonts();
  130.     InitWindows();
  131.     InitMenus();
  132.     TEInit();
  133.     InitDialogs(nil);
  134.     FlushEvents(everyEvent,0);
  135.     InitCursor();
  136.     DrawMenuBar();
  137. }
  138.  
  139. int do_init_appl(void)
  140. {
  141. short        kind;
  142. Handle        h;
  143. Rect        r;
  144. UserItemUPP    user_item_upp;
  145. CGrafPtr    saved_port;
  146. GDHandle    saved_gdh;
  147. short        i, n_menu_items;
  148. Str255        str;
  149.     /* get font id of monaco */
  150.     GetFNum("¥pMonaco", &monaco_font_id);
  151.     /* check japanease font */
  152.     h = GetResource('itlb', 1);
  153.     jap_script_available = (h != 0);
  154.     /* setup menus */
  155.     pop_font = GetMenu(131);
  156.     AddResMenu(pop_font, 'FONT');
  157.     pop_size = GetMenu(132);
  158.     pop_char = GetMenu(133);
  159.     InsertMenu(applemenu  = GetMenu(128), 0);
  160.     InsertMenu(filemenu   = GetMenu(129), 0);
  161.     InsertMenu(editmenu   = GetMenu(130), 0);
  162.     AddResMenu(applemenu, 'DRVR');
  163.     DrawMenuBar();
  164.     if(!jap_script_available) {
  165.         // japanease font not found.
  166.         // delete kanji from japanease menu.
  167.         n_menu_items = CountMItems(pop_char);
  168.         for(i=K_KANJI_START; i<=n_menu_items; i++)
  169.             DelMenuItem(pop_char, K_KANJI_START);
  170.     }
  171.     /* setup dialog */
  172.     dp = GetNewDialog(128, nil, (WindowPtr) -1);
  173.     if(dp == nil) return -1;
  174.     user_item_upp = NewUserItemProc(draw_user_item);
  175.     GetDItem(dp, K_RESULT, &kind, &h, &big_text_area);
  176.     SetDItem(dp, K_RESULT,  kind, (void*)user_item_upp, &big_text_area);
  177.     set_ctl_value(K_FONT, 1);
  178.     set_ctl_value(K_SIZE, 4);
  179.     set_ctl_value(K_CHAR, 1);
  180.     InsetRect(&big_text_area, -1, -1);
  181.     if(jap_script_available) {
  182.         GetIndString(str, 128, 1);
  183.     } else {
  184.         GetIndString(str, 128, 2);
  185.     }
  186.     SetIText(get_ditm_handle(dp, K_TEXT), str);
  187.     SelIText(dp, K_TEXT, 0, 1000);
  188.     /* setup offscreen */
  189.     GetGWorld(&saved_port, &saved_gdh);
  190.     SetRect(&r, 0, 0, K_OFF_WIDTH, K_OFF_HEIGHT);
  191.     if(NewGWorld(&off, 8, &r, nil, nil, nil) == 0) {
  192.         LockPixels(GetGWorldPixMap(off));
  193.         SetGWorld(off, nil);
  194.         EraseRect(&off->portRect);
  195.     } else {
  196.         off = nil;
  197.     }
  198.     SetGWorld(saved_port, saved_gdh);
  199.     if(off == nil) return -1;
  200.     /* setup big text buffer */
  201.     big_text_hdl = NewHandle(0);
  202.     return 0;
  203. }
  204.  
  205. long install_apple_events_handler(void)
  206. {
  207. OSErr    err;
  208. long    resp, rv;
  209.     rv = -1;
  210.     err = Gestalt(gestaltAppleEventsAttr, &resp);
  211.     if ((err == noErr) && (resp & (31 - gestaltAppleEventsPresent))) {
  212.         upp_launch = NewAEEventHandlerProc(ae_launch);
  213.         upp_opendoc = NewAEEventHandlerProc(ae_opendoc);
  214.         upp_print = NewAEEventHandlerProc(ae_print);
  215.         upp_quit = NewAEEventHandlerProc(ae_quit);
  216.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, upp_launch, 0, false);
  217.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, upp_opendoc, 0, false);
  218.         err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, upp_print, 0, false);
  219.         err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, upp_quit, 0, false);
  220.         rv = err;
  221.     }
  222.     return rv;
  223. }
  224.  
  225. /*------------- process apple events -------------*/
  226. pascal OSErr ae_launch(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon)
  227. { return noErr; }
  228. pascal OSErr ae_opendoc(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon)
  229. { return errAEEventNotHandled; }
  230. pascal OSErr ae_print(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent,  long refCon)
  231. { return errAEEventNotHandled; }
  232. pascal OSErr ae_quit(AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon)
  233. { exit_program = true; return noErr; }
  234.  
  235. /*------------- event loop -------------*/
  236. void do_main_event_loop(void)
  237. {
  238. EventRecord    an_event;
  239. WindowPtr    clicked_wp;
  240. short        itemhit;
  241. DialogPtr    clicked_dialog;
  242.     /* load and setup dialogs */
  243.     ShowWindow(dp);
  244.     SetPort(dp);
  245.     /* event loop */
  246.     create_big_text();
  247.     do {
  248.         WaitNextEvent(everyEvent, &an_event, 60, nil);
  249.         switch(an_event.what) {
  250.             case kHighLevelEvent:    AEProcessAppleEvent(&an_event);    break;
  251.             case mouseDown:
  252.                 switch(FindWindow(an_event.where, &clicked_wp)) {
  253.                     case inDrag:
  254.                         DragWindow(clicked_wp, an_event.where, &qd.screenBits.bounds);
  255.                         break;
  256.                 case inMenuBar:
  257.                     do_menu(MenuSelect(an_event.where));
  258.                 }
  259.                 break;
  260.             case keyDown:
  261.             case autoKey:
  262.                 if((an_event.modifiers & cmdKey) != 0)
  263.                     do_menu(MenuKey((char)(an_event.message & charCodeMask)));
  264.                 break;
  265.         }
  266.         if(IsDialogEvent(&an_event)) {
  267.             if(DialogSelect(&an_event, &clicked_dialog, &itemhit)) {
  268.                 switch(itemhit) {
  269.                     case K_QUIT:
  270.                         exit_program = true;
  271.                         break;
  272.                     case K_COPY:
  273.                         put_big_text_into_scrap();
  274.                         break;
  275.                     case K_CHAR:
  276.                         if(get_ctl_value(K_CHAR) == K_OTHER_CHAR)
  277.                             choose_other_char();
  278.                         create_big_text();
  279.                         break;
  280.                     default:
  281.                         create_big_text();
  282.                         break;
  283.                 }
  284.             }
  285.         }
  286.     } while(!exit_program);
  287. }
  288.  
  289. /*------------- management menus -------------*/
  290. void do_menu(long menu_and_item)
  291. {
  292. short    itemnum;
  293. Str255    da_name;
  294.     itemnum = LoWord(menu_and_item);
  295.     switch(HiWord(menu_and_item)) {
  296.         case 128: // apple menu
  297.             switch(itemnum) {
  298.                 case 1:
  299.                     Alert(1280, nil);
  300.                     break;
  301.                 default:
  302.                     GetItem(applemenu, itemnum, da_name);
  303.                     OpenDeskAcc(da_name);
  304.                     break;
  305.             }
  306.             break;
  307.         case 129: // file menu
  308.             exit_program = true;
  309.             break;
  310.         case 130: // edit menu
  311.             switch(itemnum) {
  312.                 case 8: // select all
  313.                     SelIText(dp, K_TEXT, 0, 1000);
  314.                     break;
  315.                 case 10: // Copy big text
  316.                     put_big_text_into_scrap();
  317.                     break;
  318.                 default: // DialogSelect's job
  319.                     break;
  320.             }
  321.             break;
  322.     }
  323.     HiliteMenu(0);
  324. }
  325.  
  326. void get_menu_options(void)
  327. {
  328. Str255    str;
  329.     cur_font_choosed = get_ctl_value(K_FONT);
  330.     cur_size_choosed = get_ctl_value(K_SIZE);
  331.     cur_char_choosed = get_ctl_value(K_CHAR);
  332.     GetItem(pop_font, cur_font_choosed, str);
  333.     GetFNum(str, &cur_font_id);
  334.     GetItem(pop_size, cur_size_choosed, str);
  335.     StringToNum(str, &cur_size);
  336.     if(cur_char_choosed == K_OTHER_CHAR) {
  337.         cur_char_is_kanji = other_char_is_kanji;
  338.         cur_ascii_char = other_ascii_char;
  339.         cur_kanji_char = other_kanji_char;
  340.     } else {
  341.         GetItem(pop_char, cur_char_choosed, str);
  342.         if(str[1] == ' ') {
  343.             cur_char_is_kanji = false;
  344.             cur_ascii_char = str[2];
  345.         } else {
  346.             cur_char_is_kanji = true;
  347.             BlockMove((void*)&str[1], (void*)&cur_kanji_char, 2);
  348.         }
  349.     }
  350. }
  351.  
  352. void choose_other_char(void)
  353. {
  354. DialogPtr    other_dp;
  355. GrafPtr        saved_port;
  356. short        itemhit;
  357. short        kind;
  358. Handle        h;
  359. Rect        r;
  360. Str255        str;
  361.     GetPort(&saved_port);
  362.     other_dp = GetNewDialog(129, nil, (WindowPtr) -1);
  363.     if(other_dp == nil) return;
  364.     if(other_char_is_kanji) {
  365.         str[0] = 2;
  366.         BlockMove((void*)&other_kanji_char, (void*)&str[1], 2);
  367.     } else {
  368.         str[0] = 1;
  369.         str[1] = other_ascii_char;
  370.     }
  371.     SetIText(get_ditm_handle(other_dp, 3), str);
  372.     ShowWindow(other_dp);
  373.     SetPort(other_dp);
  374.     SelIText(other_dp, 3, 0, 1000);
  375.     for(itemhit = 0; itemhit != 1;) {
  376.         GetDItem(other_dp, 1, &kind, &h, &r);
  377.         InsetRect(&r, -4, -4);
  378.         PenSize(3, 3);
  379.         FrameRoundRect(&r, 16, 16);
  380.         PenSize(1, 1);
  381.         ModalDialog(nil, &itemhit);
  382.         GetIText(get_ditm_handle(other_dp, 3), str);
  383.         switch(itemhit) {
  384.             case 1:
  385.                 if(str[0] <= 0) itemhit = 0;
  386.                 else if(str[0] > 2) itemhit = 0;
  387.                 else {
  388.                     switch(CharByte((void*)&str[1], 0)) {
  389.                         case  0:    // ascii char
  390.                             if(str[0] != 1) {
  391.                                 itemhit = 0;
  392.                             } else {
  393.                                 other_char_is_kanji = false;
  394.                                 other_ascii_char = str[1];
  395.                             }
  396.                             break;
  397.                         case -1:    // first byte of kanji
  398.                             if(str[0] != 2) {
  399.                                 itemhit = 0;
  400.                             } else {
  401.                                 other_char_is_kanji = true;
  402.                                 BlockMove(&str[1], (void*)&other_kanji_char, 2);
  403.                             }
  404.                             break;
  405.                         default:    // error.
  406.                             itemhit = 0;
  407.                             break;
  408.                     }
  409.                 }
  410.                 if(itemhit == 0) {
  411.                     SysBeep(1);
  412.                     SelIText(other_dp, 3, 0, 1000);
  413.                 }
  414.                 break;
  415.         }
  416.     }
  417.     DisposDialog(other_dp);
  418.     SetPort(saved_port);
  419. }
  420.  
  421. /*------------- Utility routines -------------*/
  422. Handle get_ditm_handle(DialogPtr xdp, short itemnum)
  423. {
  424. short        kind;
  425. Handle        h;
  426. Rect        r;
  427.     GetDItem(xdp, itemnum, &kind, &h, &r);
  428.     return h;
  429. }
  430.  
  431. short get_ctl_value(short itemnum)
  432. {
  433.     return GetCtlValue((ControlHandle)get_ditm_handle(dp, itemnum));
  434. }
  435.  
  436. void set_ctl_value(short itemnum, short value)
  437. {
  438.     SetCtlValue((ControlHandle)get_ditm_handle(dp, itemnum), value);
  439. }
  440.  
  441. /*------------- draw big text -------------*/
  442. pascal void draw_user_item(DialogPtr dp, short itemnum)
  443. {
  444. GrafPtr    saved_port;
  445. Rect    r;
  446. long    big_text_size, i, j, k, y;
  447. Ptr        p;
  448. FontInfo    cur_font_info;
  449.     GetPort(&saved_port);
  450.     SetPort(dp);
  451.     if(cur_char_is_kanji) {
  452.         TextFont(applFont);
  453.         TextSize(12);
  454.     } else {
  455.         TextFont(monaco_font_id);
  456.         TextSize(9);
  457.     }
  458.     FrameRect(&big_text_area);
  459.     r = big_text_area;
  460.     InsetRect(&r, 1, 1);
  461.     EraseRect(&r);
  462.     big_text_size = GetHandleSize(big_text_hdl);
  463.     HLock(big_text_hdl);
  464.     p = *big_text_hdl;
  465.     GetFontInfo(&cur_font_info);
  466.     y = r.top + cur_font_info.ascent + cur_font_info.descent;
  467.     for(i=0, j=0; i<big_text_size; i++) {
  468.         if( (i == (big_text_size-1)) || (p[i] == 0x0d) ) {
  469.             k = i - j;
  470.             if(k > 0) {
  471.                 MoveTo(r.left, y);
  472.                 DrawText(p, j, k);
  473.             }
  474.             y += cur_font_info.ascent + cur_font_info.descent + cur_font_info.leading;
  475.             j = i + 1;
  476.         }
  477.     }
  478.     HUnlock(big_text_hdl);
  479.     TextFont(applFont);
  480.     TextSize(12);
  481.     SetPort(saved_port);
  482. }
  483.  
  484. /*------------- create big text -------------*/
  485. void create_big_text(void)
  486. {
  487. #define K_WIDTH    76    // big text width
  488. CGrafPtr    saved_port;
  489. GDHandle    saved_gdh;
  490. FontInfo    cur_font_info;
  491. short        i, j, k, n_chars, n_lines;
  492. short        width, off_rowbytes, x, y, line_height, space_counter;
  493. char        *pix;
  494. Str255        str;
  495.     get_menu_options();
  496.     SetHandleSize(big_text_hdl, 0);
  497.     GetGWorld(&saved_port, &saved_gdh);
  498.     /* text > off */
  499.     SetGWorld(off, nil);
  500.     TextFont(cur_font_id);
  501.     TextSize(cur_size);
  502.     GetFontInfo(&cur_font_info);
  503.     GetIText(get_ditm_handle(dp, K_TEXT), str);
  504.     EraseRect(&off->portRect);
  505.     n_chars = str[0];
  506.     line_height = cur_font_info.ascent + cur_font_info.descent;
  507.     y = cur_font_info.ascent;
  508.     n_lines = 0;
  509.     for(i=j=1; i<=n_chars; i++) {
  510.         if( (i == n_chars) || (str[i] == 0x0d) ) {
  511.             k = i - j;
  512.             if(str[i] != 0x0d) k++;
  513.             if(k > 0) {
  514.                 MoveTo(0, y);
  515.                 DrawText(str, j, k);
  516.             }
  517.             j = i + 1;
  518.             y += line_height;
  519.             n_lines++;
  520.         }
  521.     }
  522.     line_height *= n_lines;
  523.     /* off > big text */
  524.     off_rowbytes = (**GetGWorldPixMap(off)).rowBytes;
  525.     off_rowbytes &= 0x7fff;
  526.     pix = (char*)GetPixBaseAddr(GetGWorldPixMap(off));
  527.     if(cur_char_is_kanji)    width = K_WIDTH / 2;
  528.     else                    width = K_WIDTH;
  529.     
  530.     for(y=0; y<line_height; y++) {
  531.         space_counter = 0;
  532.         for(x=0; x<width; x++) {
  533.             if(pix[x]) {
  534.                 // black pixel
  535.                 for( ; space_counter>0; space_counter--) add_one_char(' ');
  536.                 add_one_char(0);
  537.             } else {
  538.                 space_counter++;
  539.             }
  540.         }
  541.         add_one_char(0x0d);
  542.         pix += off_rowbytes;
  543.     }
  544.     SetGWorld(saved_port, saved_gdh);
  545.     /* draw big text */
  546.     SetPort(dp);
  547.     InvalRect(&big_text_area);
  548. }
  549.  
  550. void add_one_char(char what_char)
  551. {
  552. long    old_size;
  553. Ptr        tail_ptr;
  554.     old_size = GetHandleSize(big_text_hdl);
  555.     if(cur_char_is_kanji && (what_char != 0x0d)) {
  556.         SetHandleSize(big_text_hdl, old_size + 2);
  557.         tail_ptr = StripAddress(*big_text_hdl);
  558.         tail_ptr += old_size;
  559.         if(what_char == ' ') {
  560.             BlockMove((void*)&kanji_space, tail_ptr, 2);
  561.         } else {
  562.             BlockMove((void*)&cur_kanji_char, tail_ptr, 2);
  563.         }
  564.     } else {
  565.         SetHandleSize(big_text_hdl, old_size + 1);
  566.         tail_ptr = StripAddress(*big_text_hdl);
  567.         tail_ptr += old_size;
  568.         if(what_char == 0) {
  569.             *tail_ptr = cur_ascii_char;
  570.         } else {
  571.             *tail_ptr = what_char;
  572.         }
  573.     }
  574. }
  575.  
  576. void put_big_text_into_scrap(void)
  577. {
  578.     HLock(big_text_hdl);
  579.     ZeroScrap();
  580.     PutScrap(GetHandleSize(big_text_hdl), 'TEXT', *big_text_hdl);
  581.     HUnlock(big_text_hdl);
  582. }
  583.