wpengine.c

Go to the documentation of this file.
00001 
00002 /*  $Id: wpengine.c 1351 2006-05-04 23:16:48Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 
00030 #include "PAIGE.H"
00031 #include "PGTRAPS.H"
00032 #include "PGEXCEPS.H"
00033 #include "DEFPROCS.H"
00034 #include "MACHINE.H"
00035 #include "pgHLevel.h"
00036 
00037 #include "standard.h"
00038 
00039 #include "bitmaps.h"
00040 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00041 #include "cursor.h"
00042 #include "error.h"
00043 #include "font.h"
00044 #include "kb.h"
00045 #include "memory.h"
00046 #include "mouse.h"
00047 #include "quickdraw.h"
00048 #include "strings.h"
00049 #include "ops.h"
00050 #include "file.h"
00051 #include "resources.h"
00052 #include "scrap.h"
00053 #include "search.h"
00054 #include "timedate.h"
00055 #include "shell.h"
00056 #include "shell.rsrc.h"
00057 #include "shellprint.h"
00058 #include "shellundo.h"
00059 #include "wpengine.h"
00060 #include "wpinternal.h"
00061 #include "op.h"
00062 #include "opinternal.h"
00063 
00064 
00065 #define flrulers false /*set to false to remove all rulers add-on package calls*/
00066 
00067 #define lenfontname 32 /*number of chars reserved for font name*/
00068 
00069 #define scrollquantum 16
00070 
00071 #define i2fix(i) FixRatio (i, 1)
00072 
00073 #define fix2i(f) FixRound (f)
00074 
00075 #define defaultpgflags (NO_SMART_CUT_BIT | NO_LF_BIT | NO_HIDDEN_TEXT_BIT)
00076 
00077 #define wpdisplay_way (wpdisplayenabled ()? best_way : draw_none)
00078 
00079 
00080 WindowPtr wpwindow = nil;
00081 
00082 hdlwprecord wpdata = nil;
00083 
00084 hdlwindowinfo wpwindowinfo = nil;
00085 
00086 pg_ref wpbuffer = MEM_NULL;
00087 
00088 static hdlregion wpselectionrgn = nil;
00089 
00090 static pgm_globals mem_globals;
00091 
00092 static pg_globals ws_globals;
00093 
00094 // static wpeditingnow = 0;
00095 
00096 // static Handle hlastundodata = nil;
00097 
00098 #ifdef WIN95VERSION
00099     static boolean fldestroycaret = false; /*7.0b16 PBS: global for destroying caret in main thread on Windows.*/
00100 #endif
00101 
00102 
00103 #define ctwpstack 5 /*we can remember wp contexts up to 5 levels deep*/
00104 
00105 static short topwpstack = 0;
00106 
00107 static hdlwprecord wpstack [ctwpstack];
00108 
00109 
00110 typedef struct tywpheader { /*format of text item header stored on disk*/
00111     
00112     short versionnumber; /*important, this structure is saved on disk*/
00113     
00114     long timecreated, timelastsave;
00115     
00116     long ctsaves; /*the number of times the structure has been saved on disk*/
00117     
00118     char fontname [lenfontname]; /*the default font for the text*/
00119     
00120     short fontsize, fontstyle;
00121     
00122     long maxpos;
00123     
00124     short unused [4]; /*unused stuff*/
00125     
00126     short flags;
00127     
00128     diskrect windowrect; /*the size of the window that holds the edit record*/
00129     
00130     long varlistsize; /*variable list*/
00131     
00132     long buffersize; /*number of chars in pg_ref, stored after this header record*/
00133     
00134     char waste [52]; /*room to grow*/
00135     } tywpheader;
00136 
00137 #ifdef MACVERSION
00138     #define floneline_mask  0x8000 /*set if this is a single-line, false otherwise*/
00139     #define flruleron_mask  0x4000 /*set if the ruler should be displayed*/
00140     #define flexpandvariables_mask  0x2000 /*expand variables into text?*/
00141     #define flhilitevariables_mask  0x1000 /*show visual indication of variable text?*/
00142 #endif
00143 
00144 #ifdef WIN95VERSION
00145     #define floneline_mask  0x0080 /*set if this is a single-line, false otherwise*/
00146     #define flruleron_mask  0x0040 /*set if the ruler should be displayed*/
00147     #define flexpandvariables_mask  0x0020 /*expand variables into text?*/
00148     #define flhilitevariables_mask  0x0010 /*show visual indication of variable text?*/
00149 #endif
00150 
00151 
00152 typedef struct tyOLD42wpheader { /*format of text item header stored on disk*/
00153     
00154     short versionnumber; /*important, this structure is saved on disk*/
00155     
00156     long timecreated, timelastsave;
00157     
00158     long ctsaves; /*the number of times the structure has been saved on disk*/
00159     
00160     char fontname [lenfontname]; /*the default font for the text*/
00161     
00162     short fontsize, fontstyle;
00163     
00164     long maxpos;
00165     
00166     short unused [4]; /*unused stuff*/
00167     
00168     boolean floneline: 1; /*true if this is a single-line, false otherwise*/
00169     
00170     boolean flruleron: 1; /*true if the ruler should be displayed*/
00171     
00172     boolean flexpandvariables: 1; /*expand variables into text?*/
00173     
00174     boolean flhilitevariables: 1; /*show visual indication of variable text?*/
00175     
00176     diskrect windowrect; /*the size of the window that holds the edit record*/
00177     
00178     long varlistsize; /*variable list*/
00179     
00180     long buffersize; /*number of chars in pg_ref, stored after this header record*/
00181     
00182     char waste [52]; /*room to grow*/
00183     } tyOLD42wpheader;
00184 
00185 
00186 typedef struct tyselectinfo { /*for undo*/
00187     
00188     long startsel, endsel; /*beginning and end of selection*/
00189     
00190     long origsel; /*needed for forward delete in undoinsert*/
00191     
00192     boolean flreselect: 1; /*re-select text after un-deleting?*/
00193     
00194     boolean flrecalc: 1; /*recalc after undoing?*/
00195     
00196     hdlwprecord hwp; /*the wp record that owns this undo*/
00197     
00198     union {
00199         
00200         Handle hseldata;
00201         
00202         pg_ref hwpsel;
00203         
00204     //  rulerHandle hrulers;
00205         
00206     //  FormatHandle hformat;
00207         } u;
00208     } tyselectinfo, *ptrselectinfo, **hdlselectinfo;
00209 
00210 
00211 static boolean wpinserttexthandle (pg_ref, Handle, short, boolean);
00212 
00213 
00214 #ifdef MACVERSION
00215 #pragma mark === low-level ===
00216 #endif
00217 
00218 static PG_PASCAL (long) wpcharinfoproc (
00219         paige_rec_ptr pg, style_walk_ptr style_walker,
00220         pg_char_ptr data, long block_offset, long offset_begin, 
00221         long offset_end, long char_offset, long mask_bits) {
00222     
00223     /*
00224     if (result & WORD_SEL_BIT)
00225         ...
00226         result = ((result | !WORD_SEL_BIT) & INCLUDE_SEL_BIT)
00227     */
00228     
00229     long result;
00230     
00231     result = pgCharInfoProc (pg, style_walker, data, block_offset, offset_begin, offset_end, 
00232                 char_offset, mask_bits);
00233     
00234     if (mask_bits & (WORD_SEL_BIT | INCLUDE_SEL_BIT)) {
00235         
00236         switch (data [char_offset]) {
00237             
00238             case '.':
00239                 if ((char_offset > 0) && isalnum (data [char_offset + 1])) {
00240                 
00241                     result &= ~WORD_SEL_BIT;
00242                     result |= INCLUDE_SEL_BIT;
00243                     }
00244                 
00245                 break;
00246             
00247             case '^':
00248             case '{': case '}':
00249             case '[': case ']':
00250                 result &= ~INCLUDE_SEL_BIT;
00251                 result |= WORD_SEL_BIT;
00252                 
00253                 break;
00254             }
00255         }
00256     
00257     return (result);
00258     } /*wpcharinfoproc*/
00259 
00260 
00261 boolean wpinit (void) {
00262     
00263     pgMemStartup (&mem_globals, 0);
00264     
00265     pgInit (&ws_globals, &mem_globals);
00266     
00267 //  pgInitEmbedProcs (&ws_globals, NULL, NULL);
00268     
00269     ws_globals.def_style.procs.char_info = (char_info_proc) wpcharinfoproc;
00270 
00271     wpselectionrgn = NewRgn ();
00272     
00273     return (true);
00274     } /*wpinit*/
00275 
00276 
00277 void wpshutdown (void) {
00278     
00279     pgShutdown (&ws_globals);
00280     
00281     pgMemShutdown (&mem_globals);
00282     } /*wpshutdown*/
00283 
00284 
00285 static void setdefaultstyles (boolean flprinting) {
00286 #ifdef MACVERSION
00287 #   pragma unused (flprinting)
00288 #endif
00289 
00290     short font, size, style;
00291     bigstring bsfont;
00292     
00293     getfontsizestyle (&font, &size, &style);
00294     
00295     fontgetname (font, bsfont);
00296 
00297     pgFillBlock(ws_globals.def_font.name, FONT_SIZE * sizeof(pg_char), 0);
00298     pgBlockMove (bsfont, ws_globals.def_font.name, stringsize (bsfont));
00299     
00300     #ifdef MACVERSION
00301         ws_globals.def_style.point = (long) size << 16;     // Fixed data type
00302     #endif
00303     #ifdef WIN95VERSION
00304         // 6.0b3: scale pointsize when printing
00305         if (flprinting)
00306             ws_globals.def_style.point = MulDiv(size, shellprintinfo.scaleMult, shellprintinfo.scaleDiv) << 16;
00307         else
00308             ws_globals.def_style.point = (long) size << 16; // Fixed data type
00309     #endif
00310 
00311     ws_globals.def_style.char_width = 0;
00312     
00313     QDStyleToPaige (style, &ws_globals.def_style);
00314     } /*setdefaultstyles*/
00315 
00316 
00317 boolean wpsetglobals (void) {
00318     
00319     register hdlwprecord hwp = wpdata;
00320     register pg_ref hbuf;
00321     
00322     if (hwp == nil)
00323         return (false);
00324     
00325     hbuf = (pg_ref) (**hwp).wpbuffer;
00326     
00327     wpbuffer = hbuf; /*set global*/
00328     
00329     return (hbuf != nil);
00330     } /*wpsetglobals*/
00331 
00332 
00333 static boolean wpdisplayenabled (void) {
00334     
00335     register hdlwprecord hwp = wpdata;
00336     
00337     if (wpdata == NULL)
00338         return (false);
00339 
00340     return ((wpwindow != nil) && (**hwp).flwindowopen && !(**hwp).flinhibitdisplay);
00341     } /*wpdisplayenabled*/
00342 
00343 
00344 static undo_ref getundo (void) {
00345 
00346     return ((undo_ref) (**wpdata).hlastundodata);
00347     } /*getundo*/
00348 
00349 
00350 static void setundo (undo_ref undo) {
00351     
00352     /*
00353     12/10/96 dmb: we must maintain a flag in the undo itself, saying that 
00354     we own it. this will prevent it from being disposed.
00355     */
00356     
00357     (**wpdata).hlastundodata = (void *) undo;
00358     } /*setundo*/
00359 
00360 
00361 static void wpdisposeundo (hdlwprecord hwp) {
00362     
00363     /*
00364     divorce the wprecord from its lastinsertundo data.  one of them is 
00365     about to be disposed, and lingering attraction can lead to heap crash
00366     */
00367     
00368     undo_ref hundo;
00369     
00370     if (hwp != nil) {
00371         
00372         hundo = (undo_ref) (**hwp).hlastundodata;
00373         
00374         if (hundo != nil) { /*there was a linked undo*/
00375             
00376             pgDisposeUndo (hundo);
00377             
00378             (**hwp).hlastundodata = nil;
00379             }
00380         }
00381     } /*wpdisposeundo*/
00382 
00383 
00384 void wpresettyping (void) {
00385     
00386     /*
00387     call this routine when subsequent typing should be considered a new 
00388     operation, seperate from typing changes that have already occured.  this 
00389     should happen any time the user moves the insertion point with the mouse
00390     or cursor keys, or after certain other occurances.
00391     
00392     our task is to "close the book" on the undo we've been building by noting 
00393     the final insertion point.  we then remove our link to the undo stack 
00394     frame by clearing hlastinsertundodata
00395     
00396     12/6/96 dmb: paige implementation
00397     */
00398     
00399     (**wpdata).flstartedtyping = false;
00400     } /*wpresettyping*/
00401 
00402 
00403 static boolean wpownwindowinfo (void) {
00404     
00405     /*
00406     return true if the edit environment is "owned" by the word processor.
00407     */
00408     
00409     if (wpwindowinfo == nil)
00410         return (false);
00411     
00412     return ((**wpwindowinfo).configresnum == idwpconfig);
00413     } /*wpownwindowinfo*/
00414 
00415 
00416 static void wpdirty (boolean flchangedtext) {
00417     
00418     /*
00419     9/14/91 dmb: added flchangedcontent parameter
00420     
00421     12/4/91 dmb: don't dirty windowinfo if it's not our own
00422     
00423     2.1b4 dmb: update timelastsave on each change
00424     */
00425     
00426     register hdlwprecord hwp = wpdata;
00427     
00428     if (!flchangedtext)
00429         (**hwp).fldirtyview = true;
00430     
00431     else {
00432         
00433         (**hwp).fldirty = true; /*the structure is dirty*/
00434         
00435         (**hwp).timelastsave = timenow (); /*modification time until saved*/
00436         
00437         if (wpownwindowinfo ()) /*the window is dirty*/
00438             windowsetchanges (wpwindow, true);
00439         
00440         (*(**hwp).dirtyroutine) ();
00441         }
00442     } /*wpdirty*/
00443 
00444 
00445 static void wpdirtyselectioninfo (void) {
00446     
00447     /*
00448     make sure the ruler & menus get updated to reflect a formatting change.
00449     */
00450     
00451     if ((wpwindowinfo != nil) && wpdisplayenabled ())
00452         (**wpwindowinfo).selectioninfo.fldirty = true;
00453     } /*wpdirtyselectioninfo*/
00454 
00455 
00456 boolean wppushdata (hdlwprecord hwp) {
00457     
00458     /*
00459     when you want to temporarily work with a different wprecord, call this
00460     routine, do your stuff and then call wppopdata.
00461     */
00462     
00463     if (topwpstack >= ctwpstack) {
00464         
00465         shellinternalerror (idwpstackfull, STR_wp_stack_overflow);
00466         
00467         return (false);
00468         }
00469     
00470     wpstack [topwpstack++] = wpdata;
00471     
00472     wpdata = hwp;
00473     
00474     return (true);
00475     } /*wppushdata*/
00476         
00477 
00478 boolean wppopdata (void) {
00479     
00480     if (topwpstack <= 0)
00481         return (false);
00482     
00483     wpdata = wpstack [--topwpstack];
00484     
00485     return (true);
00486     } /*wppopdata*/
00487 
00488 
00489 #ifdef MACVERSION
00490 #pragma mark === display ===
00491 #endif
00492 
00493 
00494 static shape_ref newshape (const Rect *r) {
00495     
00496     rectangle bounds;
00497     
00498     RectToRectangle ((Rect *) r, &bounds);
00499     
00500     return (pgRectToShape (&mem_globals, &bounds));
00501     } /*newshape*/
00502 
00503 static void wppushdraw (void) {
00504     
00505     /*
00506     7/26/91 dmb: make sure that now drawing occurs to the right of tBounds
00507     */
00508     
00509 //  Rect rclip;
00510 
00511     if (wpdisplayenabled ()) {
00512         
00513         //Code change by Timothy Paustian Monday, August 21, 2000 4:31:49 PM
00514         //Must pass a CGrafPtr to pushport on OS X to avoid a crash
00515     
00516         #ifdef MACVERSION
00517 
00518             CGrafPtr thePort;
00519 
00520             #if TARGET_API_MAC_CARBON == 1
00521             thePort = GetWindowPort(wpwindow);
00522             #else
00523             thePort = (CGrafPtr)wpwindow;
00524             #endif
00525 
00526             pushport (thePort);
00527 
00528         #endif
00529 
00530         #ifdef WIN95VERSION
00531 
00532             pushport (wpwindow);
00533 
00534         #endif
00535 
00536         
00537     /*
00538         rclip = (**wpdata).wprect;
00539         
00540         rclip.right = min (rclip.right, (**wpbuffer).tBounds.right);
00541         
00542         pushclip (rclip);
00543     */
00544         }
00545     } /*wppushdraw*/
00546 
00547 
00548 static void wppopdraw (void) {
00549     
00550     if (wpdisplayenabled ()) {
00551         
00552     /*
00553         popclip ();
00554         
00555         #ifdef flwpcolor
00556         
00557         RGBForeColor (&blackcolor);
00558         
00559         #endif
00560     */
00561         
00562         popport ();
00563         }
00564     } /*wppopdraw*/
00565 
00566 
00567 short wpavailwidth (void) {
00568     
00569     /*
00570     return the available width for wrapping text on the printed page
00571     
00572     for now, we just assume 1-inch of margins (total)
00573     */
00574     
00575     return (shellprintinfo.paperrect.right - shellprintinfo.paperrect.left);
00576     } /*wpavailwidth*/
00577 
00578 
00579 static void wpsetautoscroll (pg_ref hbuf, boolean flauto) {
00580     
00581     paige_rec_ptr pg = (paige_rec_ptr) UseMemory (hbuf);
00582     
00583     if (flauto)
00584         (*pg).flags2 &= ~(NO_HAUTOSCROLL | NO_VAUTOSCROLL);
00585     else
00586         (*pg).flags2 |= (NO_HAUTOSCROLL | NO_VAUTOSCROLL);
00587     
00588     UnuseMemory (hbuf);
00589     } /*wpsetautoscroll*/
00590 
00591 
00592 static void wpvisicursor (void) {
00593     
00594     /*
00595     7/9/92 dmb: when selection isn't empty, visi endsel
00596     
00597     12/6/96 dmb: paige
00598     
00599     5.0a3 dmb: reset scrollbars
00600     */
00601     
00602     register hdlwprecord hwp = wpdata;
00603     
00604     if ((**hwp).flneverscroll)
00605         return;
00606     
00607     if (!wpdisplayenabled ()) {
00608         
00609         (**hwp).flcheckvisi = true; /*defer*/
00610         
00611         return;
00612         }
00613     
00614     wpsetautoscroll (wpbuffer, true);
00615 
00616     pgScrollToView (wpbuffer, CURRENT_POSITION, 0, 0, TRUE, wpdisplay_way);
00617     
00618     wpsetautoscroll (wpbuffer, false);
00619 
00620     wpresetscrollbars ();
00621     
00622     (**hwp).flcheckvisi = false;
00623     } /*wpvisicursor*/
00624 
00625 
00626 static boolean wpisactive () {
00627     
00628     /*
00629     wpsetglobals must have already been called
00630     */
00631     
00632     short front_back_state, perm_state;
00633     
00634     pgGetHiliteStates (wpbuffer, &front_back_state, &perm_state);
00635     
00636     return (front_back_state == activate_verb);
00637     } /*wpisactive*/
00638 
00639 
00640 /*
00641 static void getlongbounds (register Rect *r, register rectangle *bounds) {
00642     
00643     (*bounds).top = (*r).top;
00644     
00645     (*bounds).bottom = (*r).top + (shellprintinfo.paperrect.bottom - shellprintinfo.paperrect.top);
00646     
00647     (*bounds).left = (*r).left;
00648     
00649     (*bounds).right = (*r).left + wpavailwidth ();
00650     } /%getlongbounds%/
00651 */
00652 
00653 
00654 boolean wpgetdisplay (void) { /*unused 8/29/91*/
00655     
00656     /*
00657     return true if WS-Engine's display is enabled.
00658     */
00659     
00660     register hdlwprecord hwp;
00661     
00662     if (!wpsetglobals ())
00663         return (false);
00664     
00665     hwp = wpdata; /*move into register*/
00666     
00667     return ((**hwp).flwindowopen && !(**hwp).flinhibitdisplay);
00668     } /*wpgetdisplay*/
00669 
00670 
00671 boolean wpsetdisplay (boolean fldisplay) {
00672     
00673     /*
00674     enable or display wp display.  return true if state is changed.
00675     */
00676     
00677     if (!wpsetglobals ())
00678         return (false);
00679     
00680     if ((**wpdata).flinhibitdisplay != fldisplay) /*nothing to do, no change*/
00681         return (false);
00682     
00683     (**wpdata).flinhibitdisplay = !fldisplay;
00684     
00685     if (fldisplay)
00686         wptotalrecalc ();
00687     
00688     return (true);
00689     } /*wpsetdisplay*/
00690 
00691 
00692 boolean wpsetruler (register boolean flruler) {
00693     
00694     /*
00695     make sure the ruler is turned on if flruler is true, make sure it is turned
00696     off if flruler is false.
00697     
00698     return true if the state of the ruler changed.
00699     
00700     6/25/92 dmb: return false if flonelist is set
00701     */
00702     
00703     register hdlwprecord hwp = wpdata;
00704     
00705     if (!wpsetglobals ())
00706         return (false);
00707     
00708     if ((**hwp).floneline)
00709         return (false);
00710     
00711     if ((**hwp).flshowruler == flruler)
00712         return (false);
00713     
00714     (**hwp).flshowruler = flruler;
00715     
00716     #if flrulers
00717     
00718     wpdirty (false);
00719     
00720     #endif
00721     
00722     return (true);
00723     } /*wpsetruler*/
00724 
00725 
00726 boolean wpgetruler (void) {
00727     
00728     /*
00729     return true if WS-Engine's ruler is on.
00730     */
00731     
00732     if (!wpsetglobals ())   // check for nil
00733         return (false);
00734     
00735     return ((**wpdata).flshowruler);
00736     } /*wpgetruler*/
00737 
00738 
00739 static short wpgetrulerheight (void) {
00740     
00741     #if flrulers
00742     
00743     // ***
00744         
00745     #endif
00746     
00747     return (0);
00748     } /*wpgetrulerheight*/
00749 
00750 
00751 static void wpsetavailbounds (pg_ref pg) {
00752     
00753     /*
00754     5.0a2 dmb: implemented correctly
00755 
00756     5.0b9 dmb: take pg as parameter instead of using global
00757     */
00758     
00759     rectangle pagebounds;
00760     
00761     pgAreaBounds (pg, &pagebounds, NULL);
00762     
00763     pagebounds.bot_right.h = pagebounds.top_left.h + wpavailwidth ();
00764     
00765     pgSetAreaBounds (pg, &pagebounds, NULL);
00766     } /*wpsetavailbounds*/
00767 
00768 
00769 void wpsetupwindow (void) {
00770     
00771     graf_device port;
00772     
00773     if (wpsetglobals () && wpwindow) {
00774 
00775         #ifdef MACVERSION
00776             #if TARGET_API_MAC_CARBON
00777             CGrafPtr thePort = GetWindowPort(wpwindow);
00778             pgInitDevice (&ws_globals, thePort, 0, &port);
00779             #else
00780             pgInitDevice (&ws_globals, wpwindow, 0, &port);
00781             #endif
00782         #endif
00783     
00784         #ifdef WIN95VERSION
00785             pgInitDevice (&ws_globals, (generic_var) wpwindow, MEM_NULL, &port);
00786         #endif
00787     
00788         pgSetDefaultDevice (wpbuffer, &port);
00789         }
00790     } /*wpsetupwindow*/
00791 
00792 
00793 static boolean wpadjustboundstofit (void) {
00794 
00795     /*
00796     if we're editing a single line, and scrolling is allowed, sise
00797     the bounds to the text width. return true if we adjust it.
00798     */
00799 
00800     register hdlwprecord hwp = wpdata;
00801 
00802     if ((**hwp).flalwaysmeasuretext) { // set bounds to fit text
00803         
00804         rectangle linebounds, curbounds, visbounds;
00805         long width, height;
00806         
00807         pgMaxTextBounds (wpbuffer, &linebounds, false);
00808         
00809         pgAreaBounds (wpbuffer, &curbounds, &visbounds);
00810         
00811         width = linebounds.bot_right.h - linebounds.top_left.h;
00812         
00813         height = linebounds.bot_right.v - linebounds.top_left.v;
00814         
00815         (**hwp).vpixels = height;
00816         
00817         (**hwp).hpixels = width;
00818         
00819         if ((**hwp).floneline) {
00820             
00821             width = max (width, visbounds.bot_right.h - visbounds.top_left.h);
00822             
00823             if (width != curbounds.bot_right.h - curbounds.top_left.h) {
00824                 
00825                 curbounds.bot_right.h = curbounds.top_left.h + width;
00826                 
00827                 pgSetAreaBounds (wpbuffer, &curbounds, NULL);
00828 
00829                 return (true);
00830                 }
00831             }
00832         else {
00833                 
00834             if (height != curbounds.bot_right.v - curbounds.top_left.v) {
00835                 
00836                 curbounds.bot_right.v = curbounds.top_left.v + height;
00837                 
00838                 pgSetAreaBounds (wpbuffer, &curbounds, NULL);
00839 
00840                 return (true);
00841                 }
00842             }
00843         }
00844     
00845     return (false);
00846     } /*wpajustboundstofit*/
00847 
00848 
00849 boolean wpsetbufferrect (Rect rclip, Rect r) {
00850     
00851     /*
00852     5.0.1 dmb: adjust bounds to fit text here, so we can reajust 
00853     in posstedit, not preedit
00854     */
00855 
00856     rectangle bounds;
00857     shape_ref cliprgn;
00858     shape_ref boundsrgn;
00859     
00860     if (!wpsetglobals ())
00861         return (false);
00862         
00863     r.top += wpgetrulerheight ();
00864     
00865     RectToRectangle (&r, &bounds);
00866     
00867     boundsrgn = newshape (&r);
00868     
00869     cliprgn = newshape (&rclip);
00870     
00871     pgInsertPendingKeys (wpbuffer);
00872     
00873     pgSetCursorState (wpbuffer, hide_cursor);
00874     
00875     pgSetAreas (wpbuffer, cliprgn, boundsrgn, MEM_NULL);
00876     
00877     pgDisposeShape (boundsrgn);
00878     
00879     pgDisposeShape (cliprgn);
00880     
00881     pgPaginateNow (wpbuffer, CURRENT_POSITION, FALSE);
00882     
00883     (**wpdata).wprect = rclip;
00884     
00885     wpadjustboundstofit ();
00886 
00887     wpresetscrollbars (); // 5.0a3 dmb
00888     
00889     return (true);
00890     } /*wpsetbufferrect*/
00891 
00892 
00893 boolean wphidecursor (void) {
00894 
00895     /*
00896     make sure the cursor is hidden, probably in preparation for a 
00897     non-paige display operation
00898     */
00899 
00900     if (!wpsetglobals ())
00901         return (false);
00902 
00903     pgSetCursorState (wpbuffer, hide_cursor);
00904 
00905     return (true);
00906     } /*wphidecursor*/
00907 
00908 
00909 static void wpframedisplay (void) {
00910     
00911     } /*wpframedisplay*/
00912 
00913 
00914 static void wpframeselection (void) {
00915 
00916     if (wpdisplayenabled ()) {
00917         
00918     //  #ifdef MACVERSION
00919         
00920         rectangle bounds;
00921         shape_ref rgn;
00922         Rect r;
00923         
00924         if (pgCaretPosition (wpbuffer, CURRENT_POSITION, &bounds)) {
00925             
00926             RectangleToRect (&bounds, NULL, &r);
00927             
00928             #ifdef MACVERSION
00929                 RectRgn (wpselectionrgn, &r);
00930             #endif
00931             #ifdef WIN95VERSION
00932                 wpselectionrgn = CreateRectRgn (r.left, r.top, r.right, r.bottom);
00933             #endif
00934             }
00935         else {
00936         
00937             rgn = pgRectToShape (&mem_globals, MEM_NULL);
00938             
00939             pgGetHiliteRgn (wpbuffer, MEM_NULL, MEM_NULL, rgn);
00940             
00941             ShapeToRgn (rgn, 0, 0, NULL, 0, NULL, wpselectionrgn);
00942             
00943             pgDisposeShape (rgn);
00944             }
00945         
00946         grayframerrgn (wpselectionrgn);
00947         
00948     //  #endif
00949         }
00950     } /*wpframeselection*/
00951 
00952 
00953 /*
00954 static short wpgetcurrentscreenlines (short line1) {
00955     
00956     register hdlwprecord hwp = wpdata;
00957     co_ordinate pt;
00958     long offset, lastline;
00959 
00960     pt.h = (**hwp).wprect.left;
00961     
00962     pt.v = (**hwp).wprect.bottom - 1;
00963 
00964     offset = pgPtToChar (wpbuffer, &pt, NULL);
00965     
00966     lastline = pgOffsetToLineNum (wpbuffer, offset, true);
00967     
00968     return (lastline - line1 + 1);
00969     } /%wpgetcurrentscreenlines%/
00970 */
00971 
00972 
00973 static boolean wpgetscrollbarinfo (void) {
00974     
00975     register hdlwprecord hwp = wpdata;
00976     tyscrollinfo vertinfo, horizinfo;
00977     rectangle curbounds;
00978     short horizcur, vertcur, horizmax, vertmax;
00979     short unit_h, unit_v, append_h, append_v;
00980     
00981     if (!wpsetglobals ())
00982         return (false);
00983     
00984     if (!pgGetScrollValues (wpbuffer, &horizcur, &vertcur, &horizmax, &vertmax))
00985         return (false);
00986     
00987     pgGetScrollParams (wpbuffer, &unit_h, &unit_v, &append_h, &append_v);
00988     
00989     horizinfo.max = horizmax;
00990     horizinfo.cur = horizcur;
00991     
00992     vertinfo.max = vertmax;
00993     vertinfo.cur = vertcur;
00994     
00995     horizinfo.min = vertinfo.min = 0;
00996 
00997     if ((**hwp).floneline)
00998         vertinfo.max = 0;
00999     
01000     pgAreaBounds (wpbuffer, &curbounds, NULL);
01001     
01002     horizinfo.pag = curbounds.bot_right.h - curbounds.top_left.h;
01003 
01004     if (unit_h > 0)
01005         horizinfo.pag /= unit_h;
01006     
01007     vertinfo.pag = curbounds.bot_right.v - curbounds.top_left.v;
01008     
01009     if (unit_v > 0)
01010         vertinfo.pag /= unit_v;
01011     //  vertinfo.pag = wpgetcurrentscreenlines (vertinfo.cur);
01012     
01013     (**hwp).horizscrollinfo = horizinfo;
01014     
01015     (**hwp).vertscrollinfo = vertinfo;
01016     
01017     return (true);
01018     } /*wpgetscrollbarinfo*/
01019 
01020 
01021 static void wpcheckscrollpos (void) {
01022     
01023     /*
01024     called after an edit, we're making sure that, in case a lot of text 
01025     was deleted, the whole document isn't scrolled up above the screen
01026     
01027     normal visiing won't account for this, since our internal scroll position 
01028     is based on absolute values
01029     
01030     12/6/96 dmb: paige implementation is easy!
01031     */
01032     
01033     pgAdjustScrollMax (wpbuffer, wpdisplay_way);
01034     } /*wpcheckscrollpos*/
01035 
01036 
01037 static void wpredrawscrollbars (void) {
01038     
01039     (*(**wpdata).setscrollbarsroutine) ();
01040     } /*wpredrawscrollbars*/
01041 
01042 
01043 void wpresetscrollbars (void) {
01044     
01045     if (!wpsetglobals ())
01046         return;
01047     
01048     if (!(**wpdata).flneverscroll) {
01049         
01050         wpgetscrollbarinfo ();
01051         
01052         wpredrawscrollbars ();
01053         }
01054     } /*wpresetscrollbars*/
01055 
01056 
01057 boolean wpgetcontentsize (long *width, long *height) {
01058     
01059     /*
01060     12/13/91 dmb: account for ruler height
01061     */
01062     
01063     rectangle bounds;
01064     
01065     if (!wpsetglobals ())
01066         return (false);
01067     
01068     pgMaxTextBounds (wpbuffer, &bounds, true);
01069     
01070     *width = bounds.bot_right.h - bounds.top_left.h + 10; /*leave some gray*/
01071     
01072     *height = bounds.bot_right.v - bounds.top_left.v + wpgetrulerheight ();
01073     
01074     return (true);
01075     } /*wpgetcontentsize*/
01076 
01077 
01078 static pg_ref wpnewpg (Handle htext, const Rect *rclip, const Rect *rbounds, tywpflags wpflags, boolean fldisplay) {
01079     
01080     /*
01081     create a new pg rec containing the given text
01082 
01083     7.1b41 PBS: Fix bug with large fonts settings on Windows. Don't use USE_NO_DEVICE unless
01084     currentport is nil. Use old code on Macs (to be conservative, since there's no bug there.
01085     */
01086     
01087     long flags = defaultpgflags | NO_EDIT_BIT;
01088     shape_ref visarea, pagearea;
01089     pg_ref pg = MEM_NULL;
01090     short draw_mode;
01091     generic_var device;
01092     
01093     #ifdef WIN95VERSION /*PBS 7.1b41: fix large fonts bug.*/
01094 
01095         device = (generic_var) getport ();
01096 
01097         if (fldisplay)      
01098             draw_mode = best_way;
01099             
01100         else {
01101 
01102             if (device == MEM_NULL)
01103                 device = USE_NO_DEVICE;
01104 
01105             draw_mode = draw_none;
01106             } /*else*/
01107 
01108     #endif
01109 
01110     #ifdef MACVERSION /*PBS 7.1b41: old code, since there's no bug on Macs.*/
01111 
01112         if (fldisplay) {
01113     
01114             device = (generic_var) getport ();
01115             
01116             draw_mode = best_way;
01117             } /*if*/
01118             
01119         else {
01120 
01121             device = USE_NO_DEVICE;
01122 
01123             draw_mode = draw_none;
01124             } /*else*/
01125 
01126     #endif
01127 
01128 
01129     if ((wpflags & wponeline) != 0)
01130         flags |= NO_WRAP_BIT; // | EXTERNAL_SCROLL_BIT));
01131     
01132     visarea = newshape (rclip);
01133     
01134     pagearea = newshape (rbounds);
01135 
01136     setdefaultstyles ((wpflags & wpprinting) != 0);
01137     
01138     PG_TRY (&mem_globals) {
01139     
01140         pg = pgNew (&ws_globals, device, visarea, pagearea, MEM_NULL, flags);
01141         }
01142     PG_CATCH {
01143     
01144         pgFailureDispose (pg);
01145         
01146         pg = MEM_NULL;
01147         
01148         memoryerror ();
01149         }
01150     PG_ENDTRY;
01151     
01152     pgDisposeShape (visarea);
01153     
01154     pgDisposeShape (pagearea);
01155     
01156     if ((pg != MEM_NULL) && (htext != nil)) {
01157     
01158         if (!wpinserttexthandle (pg, htext, draw_mode, false)) {
01159             
01160             pgDispose (pg);
01161             
01162             pg = MEM_NULL;
01163             }
01164         }
01165     
01166     return (pg);
01167     } /*wpnewpg*/
01168 
01169 
01170 static boolean wpapplyhtmlstyles (Handle htext, pg_ref pg, boolean flredraw) {
01171 
01172     /*
01173     7.0b28 PBS: Apply HTML styles to the selection. This routine understands bold, italic,
01174     underline, and links. Hide the HTML tags and format the enclosed tag as if in a
01175     web browser.
01176 
01177     If pg is nil, the caller just wants to know if this routine *would* apply HTML
01178     styles. In that case, don't actually apply any styles; return just before the first
01179     would-be application. If no styles would be applied, return false.
01180     */
01181 
01182     long sizeopenstack = 0;
01183     long stackopenleft [256];
01184     long stackopenright [256];
01185     char stackopentag [256];
01186     char tagvalue, lasttagvalue = 0;
01187     char ch;
01188     long i = 0;
01189     long lentext;
01190     boolean flintag = false;
01191     boolean flokaytag = false;
01192     long ixleft, ixright;
01193     select_pair range, deleterange;
01194     boolean flstyleapplied = false;
01195     RGBColor linkcolor;
01196     
01197     linkcolor = darkbluecolor;
01198     
01199     #ifdef WIN95VERSION
01200         linkcolor = darkgreencolor;
01201     #endif
01202 
01203     lentext = gethandlesize (htext);
01204 
01205     while (true) {
01206     
01207         ch = (*htext) [i];
01208     
01209         switch (ch) {
01210 
01211             case '<':
01212 
01213                 if (i + 2 > lentext)
01214                     break;
01215 
01216                 if ((*htext) [i + 1] == '/') {
01217                     
01218                     if (i + 3 > lentext)
01219                         break;
01220                 
01221                     tagvalue = (*htext) [i + 2];
01222                 
01223                     tagvalue = tolower (tagvalue);
01224                 
01225                     if ((tagvalue == 'a') || (tagvalue == 'b') || (tagvalue == 'i') || (tagvalue == 'u')) {
01226                     
01227                         if ((*htext) [i + 3] == '>') {
01228                         
01229                             if (sizeopenstack > 0) {
01230                             
01231                                 if (tagvalue == stackopentag [sizeopenstack]) {
01232                                 
01233                                     flstyleapplied = true;
01234                                     
01235                                     if ((void *)pg == NULL) /*Caller wants to know if styles *would* be applied.*/
01236                                         goto exit;
01237 
01238                                     deleterange.begin = i;
01239 
01240                                     deleterange.end = i + 4;
01241 
01242                                     pgSetStyleBits (pg, 0x400, -1, &deleterange, false);
01243 
01244                                     ixleft = stackopenleft [sizeopenstack];
01245                                 
01246                                     ixright = stackopenright [sizeopenstack];
01247 
01248                                     deleterange.begin = ixleft;
01249 
01250                                     deleterange.end = ixright + 1;
01251 
01252                                     pgSetStyleBits (pg, 0x400, -1, &deleterange, false);
01253                             
01254                                     sizeopenstack--;
01255                                 
01256                                     lentext = gethandlesize (htext);
01257 
01258                                     range.begin = ixright + 1;
01259 
01260                                     range.end = i;
01261 
01262                                     lasttagvalue = tagvalue;
01263 
01264                                     if (tagvalue == 'b')
01265         
01266                                         pgSetStyleBits (pg, bold, bold, &range, false);
01267                                     
01268                                     if (tagvalue == 'i')
01269                                         
01270                                         pgSetStyleBits (pg, italic, italic, &range, false);
01271 
01272                                     if (tagvalue == 'u')
01273                                         
01274                                         pgSetStyleBits (pg, underline, underline, &range, false);
01275 
01276                                     if (tagvalue == 'a') {
01277 
01278                                         pgSetStyleBits (pg, underline, underline, &range, false);
01279 
01280                                         pgSetTextColor (pg, &linkcolor, &range, false);
01281                                         } /*if*/
01282                                     } /*if*/
01283                                 } /*if*/
01284                             } /*if*/
01285                         } /*if*/
01286                     } /*if*/
01287         
01288                 else {
01289                 
01290                     flokaytag = false;
01291 
01292                     tagvalue = (*htext) [i + 1];
01293                 
01294                     tagvalue = tolower (tagvalue);
01295                 
01296                     if ((tagvalue == 'a') || (tagvalue == 'b') || (tagvalue == 'i') || (tagvalue == 'u')) {
01297                     
01298                         if (tagvalue == 'a') {
01299                         
01300                             if (i + 6 > lentext)
01301                                 break;
01302 
01303                             if ((*htext) [i + 2] == ' ') {
01304                             
01305                                 if (tolower ((*htext) [i + 3]) == 'h')
01306                                     
01307                                     flokaytag = true;
01308                                 } /*if*/
01309                             } /*if*/
01310 
01311                         else {
01312                         
01313                             if ((*htext) [i + 2] == '>')
01314                             
01315                                 flokaytag = true;
01316                             } /*else*/
01317 
01318                         if (flokaytag) {
01319                             
01320                             flintag = true;
01321 
01322                             sizeopenstack++;
01323 
01324                             stackopentag [sizeopenstack] = tagvalue;
01325 
01326                             stackopenleft [sizeopenstack] = i;
01327                             } /*if*/
01328                         } /*if*/
01329                     } /*else*/
01330 
01331                 break;
01332 
01333             case '>':
01334         
01335                 if (flintag) {
01336                     
01337                     flintag = false;
01338                 
01339                     stackopenright [sizeopenstack] = i;
01340                     } /*if*/
01341             } /*switch*/
01342     
01343         i++;
01344 
01345         if (i >= lentext)
01346 
01347             break;
01348         } /*while*/
01349 
01350     if (flredraw) { /*defer drawing until the end.*/
01351 
01352         if (lasttagvalue == 'b') {
01353 
01354             pgSetStyleBits (pg, bold, bold, &range, true);
01355 
01356             pgSetStyleBits (pg, bold, bold, &range, true);
01357             }
01358 
01359         
01360         if (lasttagvalue == 'i') {
01361             
01362             pgSetStyleBits (pg, italic, italic, &range, true);
01363 
01364             pgSetStyleBits (pg, italic, italic, &range, true);
01365             }
01366 
01367         if (lasttagvalue == 'u') {
01368 
01369             pgSetStyleBits (pg, underline, underline, &range, true);
01370 
01371             pgSetStyleBits (pg, underline, underline, &range, true);
01372             }
01373 
01374         if (lasttagvalue == 'a') {
01375 
01376             pgSetStyleBits (pg, underline, underline, &range, true);
01377             pgSetStyleBits (pg, underline, underline, &range, true);
01378 
01379             pgSetTextColor (pg, &linkcolor, &range, true);
01380             } /*if*/
01381         } /*if*/
01382 
01383     exit:
01384 
01385     return (flstyleapplied);
01386     } /*wpapplyhtmlstyles*/
01387 
01388 
01389 #if 0
01390 
01391 static boolean wpfilterstyles (Handle htext, pg_ref pg, boolean redraw) {
01392 
01393     /*
01394     7.0b28: if this is an outline of some kind, and it's in HTML mode,
01395     call the appropriate script.
01396     */
01397 
01398     if (outlinedata == NULL)
01399         return (false);
01400 
01401     if ((**outlinedata).flhtml)
01402         return (wpapplyhtmlstyles (htext, pg, redraw));
01403 
01404     return (false);
01405     } /*wpfilterstyles*/
01406 
01407 #endif
01408 
01409 
01410 boolean wpmeasuretext (Handle htext, Rect *r, tywpflags wpflags) {
01411     
01412     /*
01413     wrapping htext to fit the width of r, set the rectangle's height to fit.
01414     
01415     if htext is shorter than r's width, set the width to fit the (one) line.
01416     */
01417     
01418     pg_ref pg;
01419     rectangle bounds;
01420     
01421     pg = wpnewpg (htext, r, r, wpflags, false);
01422     
01423     if (pg == MEM_NULL)
01424         return (false);
01425     
01426     pgMaxTextBounds (pg, &bounds, true);
01427     
01428     RectangleToRect (&bounds, 0, r);
01429     
01430     pgDispose (pg);
01431     
01432     return (true);
01433     } /*wpmeasuretext*/
01434 
01435 
01436 boolean wpdrawtext (Handle htext, const Rect *rclip, const Rect *rtext, tywpflags wpflags) {
01437 
01438     /*
01439     6.0a14 dmb: if updating on Win, must use wpupdate's device  logic
01440     */
01441 
01442     pg_ref pg;
01443     graf_device port;
01444     boolean flupdating = false;
01445     boolean flprinting = false;
01446 
01447     if (wpflags == 0)
01448         wpflags = defaultpgflags;
01449         
01450     flprinting = (wpflags & wpprinting) != 0;
01451 
01452     #ifdef WIN95VERSION
01453 
01454         if (shellwindowinfo != nil)
01455             flupdating = (**shellwindowinfo).drawrgn != nil;
01456     #endif
01457     
01458     pg = wpnewpg (htext, rclip, rtext, wpflags, !flupdating && !flprinting);
01459     
01460     if (pg == MEM_NULL)
01461         return (false);
01462     
01463     if (flprinting) {
01464 
01465         #ifdef MACVERSION
01466             pgInitDevice (&ws_globals, shellprintinfo.printport, 0, &port);
01467         #endif
01468 
01469         #ifdef WIN95VERSION
01470             pgInitDevice (&ws_globals, MEM_NULL, (long) shellprintinfo.printport, &port);
01471         #endif
01472         
01473         //pgSetDefaultDevice (pg, &port);
01474             
01475         PG_TRY (&mem_globals)
01476         {
01477             pgDisplay (pg, &port, MEM_NULL, MEM_NULL, NULL, direct_copy);
01478         }
01479         PG_CATCH
01480         {
01481         }
01482         PG_ENDTRY;
01483 
01484     //  pgPrintToPage (pg, &port, 0, &r, best_way);
01485         
01486         pgCloseDevice (&ws_globals, &port);
01487         }
01488     else if (flupdating) {
01489 
01490         #ifdef WIN95VERSION
01491             pgInitDevice (&ws_globals, (generic_var) getcurrentDC (), MEM_NULL, &port);
01492             port.machine_ref3 = port.machine_var; // default place to get DC
01493             port.machine_var = 0; //can't GetDC from a HDC
01494             
01495             PG_TRY (&mem_globals)
01496             {
01497                 pgDisplay (pg, &port, MEM_NULL, MEM_NULL, NULL, direct_copy);
01498             }
01499             PG_CATCH
01500             {
01501             }
01502             PG_ENDTRY;
01503             
01504             pgCloseDevice (&ws_globals, &port);
01505         #endif
01506         }
01507     
01508     pgDispose (pg);
01509     
01510     return (true);
01511     } /*wpdrawtext*/
01512 
01513 
01514 boolean wpgetselrect (Rect *r) {
01515     
01516     /*
01517     set selrect to be the rectangle enclosing the current caret position.  
01518     intended to be used for autoscrolling
01519 
01520     dmb 12/5/96: paige
01521     */
01522     
01523     shape_ref rgn;
01524     rectangle bounds;
01525     
01526     if (!wpsetglobals ())
01527         return (false);
01528     
01529     if (!pgCaretPosition (wpbuffer, CURRENT_POSITION, &bounds)) {
01530         
01531         rgn = pgRectToShape (&mem_globals, MEM_NULL);
01532 
01533         pgGetHiliteRgn (wpbuffer, MEM_NULL, MEM_NULL, rgn);
01534 
01535         pgShapeBounds (rgn, &bounds);
01536         
01537         pgDisposeShape (rgn);
01538         }
01539     
01540     RectangleToRect (&bounds, 0, r);
01541     
01542     return (true);
01543     } /*wpgetselrect*/
01544 
01545 
01546 boolean wpgetselpoint (Point *pt) {
01547     
01548     /*
01549     return in pt.h the pixel offset of the left edge of the caret.  intended 
01550     to be passed to wpsetselpoint to restore the same position when 
01551     cursoring up or down through headlines
01552 
01553     dmb 12/5/96: paige
01554     */
01555     
01556     long startsel, endsel;
01557     rectangle r;
01558     
01559     if (!wpsetglobals ())
01560         return (false);
01561     
01562     pgGetSelection (wpbuffer, &startsel, &endsel);
01563     
01564     pgCharacterRect (wpbuffer, endsel, TRUE, TRUE, &r);
01565     
01566     (*pt).v = r.top_left.v;
01567     
01568     (*pt).h = r.top_left.h;
01569     
01570     return (true);
01571     } /*wpgetselpoint*/
01572 
01573 
01574 boolean wpsetselpoint (Point pt) {
01575     
01576     /*
01577     re-establish pt.h as the horizontal pixel offset of the cursor.  (probably 
01578     after cursoring up or down into a new headline
01579 
01580     dmb 12/5/96: paige
01581 
01582     5.0b8 dmb: make it work with non-oneline wps
01583     */
01584     
01585     long startsel, endsel;
01586     long offset;
01587     rectangle r;
01588     co_ordinate point;
01589     
01590     if (!wpsetglobals ())
01591         return (false);
01592     
01593     point.h = pt.h;
01594 
01595     point.v = pt.v;
01596     
01597 //  if ((**wpdata).floneline) {
01598     
01599         pgGetSelection (wpbuffer, &startsel, &endsel);
01600         
01601         pgCharacterRect (wpbuffer, endsel, TRUE, TRUE, &r);
01602         
01603         point.v = r.top_left.v + 1;
01604 //      }
01605     
01606     offset = pgPtToChar (wpbuffer, &point, NULL);
01607     
01608     pgSetSelection (wpbuffer, offset, offset, 0, wpdisplayenabled ());
01609     
01610     return (true);
01611     } /*wpsetselpoint*/
01612 
01613 
01614 boolean wpscroll (register tydirection dir, boolean flpage, long ctscroll) {
01615     
01616     /*
01617     12/27/91 dmb: added call to wpcheckscrollpos to make sure we correct 
01618     WS-Engine oddities
01619 
01620     5.0.1 dmb: handle zero, negative scroll amounts
01621     */
01622     
01623     hdlwprecord hwp = wpdata;
01624     long dh = scroll_none;
01625     long dv = scroll_none;
01626     long absh = (**hwp).horizscrollinfo.cur;
01627     long absv = (**hwp).vertscrollinfo.cur;
01628     boolean fltoend = ctscroll == longinfinity;
01629     
01630     if (!wpsetglobals ()) 
01631         return (false);
01632     
01633     if (ctscroll == 0)
01634         return (true);
01635 
01636     if (ctscroll < 0) {
01637         
01638         ctscroll = -ctscroll;
01639 
01640         dir = oppositdirection (dir);
01641         }
01642 
01643     switch (dir) {
01644         
01645         case up:
01646             if (flpage)
01647                 dv = -scroll_page;
01648             else if (fltoend)
01649                 absv = (**hwp).vertscrollinfo.max;
01650             else if (ctscroll > 1)
01651                 absv = absv + ctscroll;
01652             else
01653                 dv = -scroll_unit;
01654             
01655             break;
01656         
01657         case down:
01658             if (flpage)
01659                 dv = scroll_page;
01660             else if (fltoend)
01661                 absv = (**hwp).vertscrollinfo.min;
01662             else if (ctscroll > 1)
01663                 absv = absv - ctscroll;
01664             else
01665                 dv = scroll_unit;
01666             
01667             break;
01668         
01669         case left:
01670             if (flpage)
01671                 dh = -scroll_page;
01672             else if (fltoend)
01673                 absh = (**hwp).horizscrollinfo.max;
01674             else if (ctscroll > 1)
01675                 absh = absh + ctscroll;
01676             else
01677                 dh = -scroll_unit;
01678             
01679             break;
01680         
01681         case right:
01682             if (flpage)
01683                 dh = scroll_page;
01684             else if (fltoend)
01685                 absh = (**hwp).horizscrollinfo.min;
01686             else if (ctscroll > 1)
01687                 absh = absh - ctscroll;
01688             else
01689                 dh = scroll_unit;
01690             
01691             break;
01692         
01693         default:
01694             /* nothing to do */
01695             break;
01696         }
01697     
01698     if ((dv == scroll_none) && (dh == scroll_none))
01699         pgSetScrollValues (wpbuffer, absh, absv, false, wpdisplay_way);
01700     else
01701         pgScroll (wpbuffer, dh, dv, wpdisplay_way);
01702     
01703     #if flrulers
01704     
01705     if (dh && (**hwp).flshowruler) {
01706         
01707         // *** redraw ruler
01708         }
01709     
01710     #endif
01711     
01712     wpresetscrollbars ();
01713     
01714     wpcheckscrollpos ();
01715     
01716     if (wpownwindowinfo ()) {
01717 
01718         shellupdatescrollbars (wpwindowinfo);
01719 
01720         pushclip ((**wpwindowinfo).contentrect);
01721         
01722         wpframedisplay ();
01723         
01724         popclip ();
01725         }
01726     
01727     return (true);
01728     } /*wpscroll*/
01729 
01730 
01731 void wpactivate (boolean flactivate) {
01732     
01733     /*
01734     5.0d16 dmb: if flactivate is -1, don't outline selection; caller 
01735     is about to dispose wp, and doesn't want selection to show
01736 
01737     5.1b23 dmb: reestablish globals after destroying caret in main thread
01738     
01739     5.1.5b7 dmb: ...no, do it last; wpdata could be gone
01740 
01741     7.0b16 PBS: set fldestroycaret global when it should be destroyed. (Windows).
01742     Destroy caret from main thread, in wpidle. Because, on Windows, the caret
01743     can only be destroyed from the main thread.
01744     */
01745 
01746     boolean flisactive;
01747 //  boolean fldestroycaret;
01748     
01749     if (!wpsetglobals ())
01750         return;
01751     
01752     if (!wpdisplayenabled ())
01753         return;
01754     
01755     flisactive = wpisactive ();
01756     
01757     wppushdraw ();
01758     
01759     pushvalidrgnclip ();
01760     
01761     if (flactivate && flactivate != (boolean) -1) {
01762         
01763         if (!flisactive)
01764             wpframeselection ();
01765         
01766         pgSetHiliteStates (wpbuffer, activate_verb, no_change_verb, TRUE);
01767 
01768         #ifdef WIN95VERSION
01769 
01770             fldestroycaret = false; /*7.0b16 PBS: make sure the caret doesn't get destroyed*/
01771 
01772         #endif
01773 
01774         }
01775     else {
01776         pgSetHiliteStates (wpbuffer, deactivate_verb, no_change_verb, TRUE);
01777         
01778         #ifdef MACVERSION
01779         
01780             pgSetCursorState (wpbuffer, hide_cursor);
01781 
01782         #endif
01783         
01784         #ifdef WIN95VERSION
01785         
01786             /*
01787             7.0b16 PBS: destroy caret in main thread, in wpidle.
01788             On Windows, you can only destroy carets in the main thread.
01789             */
01790 
01791             fldestroycaret = true;
01792 
01793         #endif
01794         
01795         if (flisactive)
01796             if (flactivate != (boolean) -1)
01797                 wpframeselection ();
01798         }
01799     
01800     popclip ();
01801     
01802     if (flactivate && (**wpdata).flcheckvisi)
01803         wpvisicursor ();
01804     
01805     wppopdraw ();
01806     
01807     #ifdef WIN95VERSION
01808     //  if (fldestroycaret)
01809         //  shelldestoycaretinmainthread();
01810     #endif
01811     } /*wpactivate*/
01812 
01813 
01814 void wpupdate (void) {
01815     
01816     /*
01817     5.0b19 dmb: I can't for the life of me figure out what's going on, but Paige 
01818     somehow doesn't respect the clipping region during updates. so it can redraw
01819     text where we can't frame the selection. to keep things reasonably in sync, 
01820     the best thing we can do is _not_ frame the selection during updates.
01821     obviously, this only affects inactive windows.
01822 
01823     6.0a10 dmb: ugly graf_device hacking to get Paige to use the currentportDC 
01824     during updates, which is set up by BeginUpdate and is not connected to a HWND
01825     */
01826 
01827     if (wpsetglobals ()) {
01828         
01829         #ifdef gray3Dlook
01830             Rect rcontent = (**wpdata).wprect;
01831         #endif
01832         graf_device_ptr updateport = NULL;
01833         hdlregion updatergn = nil;
01834         
01835         #ifdef WIN95VERSION
01836         graf_device port;
01837         
01838         updatergn = (**shellwindowinfo).drawrgn;
01839         
01840         if (updatergn != nil) {
01841             pgInitDevice (&ws_globals, (generic_var) getcurrentDC (), MEM_NULL, &port);
01842             port.machine_ref3 = port.machine_var; // default place to get DC
01843             port.machine_var = 0; //can't GetDC from a HDC
01844             updateport = &port;
01845             }
01846         #endif
01847 
01848         #if flrulers
01849         
01850             if (wpgetruler ())
01851                 ; // *** 
01852         
01853         #endif
01854 
01855         #ifdef gray3Dlook
01856             pushbackcolor (&whitecolor);
01857         
01858             eraserect (rcontent);
01859         #endif
01860 
01861         if (updatergn == nil)
01862             pgErasePageArea (wpbuffer, MEM_NULL);
01863 
01864         PG_TRY (&mem_globals)
01865         {
01866             pgDisplay (wpbuffer, updateport, MEM_NULL, MEM_NULL, NULL, direct_copy); /*direct_or*/
01867         }
01868         PG_CATCH
01869         {
01870         }
01871         PG_ENDTRY;
01872         
01873         #ifdef gray3Dlook
01874             popbackcolor ();
01875         #endif
01876         
01877         if (!wpisactive ())
01878             wpframeselection ();
01879         
01880         wpframedisplay ();
01881         
01882         #ifdef WIN95VERSION
01883             if (updatergn != nil)
01884                 pgCloseDevice (&ws_globals, &port);
01885         #endif
01886         }
01887     } /*wpupdate*/
01888 
01889 
01890 boolean wppagesetup (void) {
01891     
01892     if (!wpsetglobals ())
01893         return (false);
01894     
01895     wpsetavailbounds (wpbuffer);
01896     
01897     shellinvalcontent (wpwindowinfo);
01898     
01899     return (true);
01900     } /*wppagesetup*/
01901 
01902 
01903 boolean wpsetprintinfo (void) {
01904     
01905     /*
01906     5.0fc3 dmb: implemented, but only by returning infinity.
01907     otherwise, we'd have to set up our bounding rectangle to 
01908     the print page.,but we really don't need a real number
01909     here; we'll just return false from wpprint when we're done.
01910     */
01911     
01912     rectangle r;
01913     
01914     if (!wpsetglobals ())
01915         return (false);
01916     
01917     RectToRectangle (&shellprintinfo.paperrect, &r);
01918     
01919     shellprintinfo.ctpages = infinity; //pgNumPages (wpbuffer, &r);
01920     
01921     return (true);
01922     } /*wpsetprintinfo*/
01923 
01924 
01925 static graf_device wpprintdevice;
01926 
01927 
01928 boolean wpbeginprint (void) {
01929 
01930     #ifdef MACVERSION
01931         //Code change by Timothy Paustian Monday, June 19, 2000 2:21:51 PM
01932         //Changed to Opaque call for Carbon
01933         //we have trouble here. Paige expects a GrafPort, I will have to 
01934         //decide how to fix this when I get to the engine.
01935     return(false);
01936     //  pgInitDevice (&ws_globals, shellprintinfo.printport, 0, &wpprintdevice);
01937     #endif
01938 
01939     #ifdef WIN95VERSION
01940         pgInitDevice (&ws_globals, MEM_NULL, (long) shellprintinfo.printport, &wpprintdevice);
01941     #endif
01942     
01943     if (wpdata != nil)
01944         (**wpdata).printpos = 0;
01945 
01946     return (true);
01947     } /*wpbeginprint*/
01948 
01949 
01950 boolean wpendprint (void) {
01951     
01952     pgCloseDevice (&ws_globals, &wpprintdevice);
01953 
01954     return (true);
01955     } /*wpendprint*/
01956 
01957 
01958 boolean wpprint (short pagenumber) {
01959     
01960     /*
01961     4.1b6 dmb: call SetFractEnable(true) so tab columns will line up
01962     */
01963     
01964     /* kw - 2005-12-05 remove this after print error correction */
01965 #if TARGET_API_MAC_CARBON == 1
01966     return (false);
01967 #else
01968     register hdlwprecord hwp = wpdata;
01969     long nextpos = 0;
01970     rectangle r;
01971     
01972     if (!wpsetglobals ())
01973         return (false);
01974     
01975     RectToRectangle (&shellprintinfo.paperrect, &r);
01976     
01977     wpresettyping ();
01978     
01979     (**hwp).flprinting = true;
01980     
01981     nextpos = pgPrintToPage (wpbuffer, &wpprintdevice, (**hwp).printpos, &r, best_way);
01982     
01983     (**hwp).flprinting = false;
01984     
01985     (**hwp).printpos = nextpos; /*copy from local, used to avoid locking handle*/
01986     
01987     return (nextpos > 0);
01988 #endif
01989     } /*wpprint*/
01990 
01991 
01992 #ifdef MACVERSION
01993 #pragma mark === read / write ===
01994 #endif
01995 
01996 
01997 static 
01998 pascal void wptrackclick (hdlwprecord wp, Point pt) {
01999 #pragma unused(wp)
02000 
02001     /*
02002     12/16/91 dmb: update scrollbars every time.  (don't need to check dirtyness, 
02003     because no drawing occurs if unchanged.)
02004     */
02005     
02006     rectangle visbounds;
02007     tydirection dir;
02008     Rect r;
02009     static unsigned long lastautoscroll = 0;
02010     #define autoscrollticks 5
02011     
02012     if (gettickcount () - lastautoscroll < autoscrollticks)
02013         return;
02014     
02015     lastautoscroll = gettickcount ();
02016     
02017     pgAreaBounds (wpbuffer, NULL, &visbounds);
02018     
02019     RectangleToRect (&visbounds, NULL, &r);
02020     
02021     if (mousecheckautoscroll (pt, r, true, &dir)) // horizontal?
02022         wpscroll (dir, false, 1);
02023     
02024     if (mousecheckautoscroll (pt, r, false, &dir)) // vertical?
02025         wpscroll (dir, false, 1);
02026     
02027     if (wpownwindowinfo ())
02028         shellupdatescrollbars (wpwindowinfo);
02029     } /*wptrackclick*/
02030 
02031 
02032 //Code change by Timothy Paustian Wednesday, August 2, 2000 9:45:12 PM
02033 //I had a crash with wptrackclickDesc. I found I can get away with a proc ptr.
02034 #if TARGET_RT_MAC_CFM
02035     #if TARGET_API_MAC_CARBON == 1
02036     //we can get away with a straight proc ptr here.
02037         #define wptrackclickUPP (wptrackclick)
02038     #else   
02039         static RoutineDescriptor wptrackclickDesc = BUILD_ROUTINE_DESCRIPTOR (uppTrackClickProcInfo, wptrackclick);
02040         #define wptrackclickUPP (&wptrackclickDesc)
02041 
02042     #endif
02043 #else
02044 
02045     #define wptrackclickUPP (&wptrackclick)
02046 #endif
02047 
02048 
02049 
02050 
02051 #ifdef MACVERSION
02052     #include <WSE.h>
02053 #endif
02054 
02055 #ifdef WIN95VERSION
02056     typedef void * UniversalProcPtr;
02057     #define FixRound(x) (x.whole)
02058     #include "WSE.h"
02059 #endif
02060 
02061 #define rulerheaderlen (sizeof (rulerRecord) + sizeof (rulerInfo) + 2 * sizeof (Handle))
02062 
02063 
02064 static shape_ref newlongshape (const LongRect *r) { // r is in disk byte format
02065     
02066     rectangle bounds;
02067     
02068     bounds.top_left.h = conditionallongswap ((*r).left);
02069     
02070     bounds.top_left.v = conditionallongswap ((*r).top);
02071     
02072     bounds.bot_right.h = conditionallongswap ((*r).right);
02073     
02074     bounds.bot_right.v = conditionallongswap ((*r).bottom);
02075     
02076     return (pgRectToShape (&mem_globals, &bounds));
02077     } /*newlongshape*/
02078 
02079 
02080 static boolean unpackwordsolutionenginefile (Handle hpacked, pg_ref *pg) {
02081 
02082     /*
02083     1/2/97 dmb: looking at the wse asm source, it appears that the structure 
02084     of a packed handle is this:
02085     
02086         [WSRec]
02087             ws.tHandle is _size_ of text block array
02088             ws.tFormat is _size_ of format rec array
02089         [TextStuff array]
02090             tx.TBLines is _size_ of line array
02091             tx.TBHandle is _size_ of text
02092             tx.TBCtl is _size of control char run
02093         [FormatHandle array]
02094         [raw data]
02095             the text / lines / crs pointed to by each text block, sequentially
02096 
02097     5.0a10 dmb: omit trailing nulls in each text block. (two in final block)
02098 
02099     5.0b18 dmb: only the final text block has the trailing nulls.
02100 
02101     5.0b18 dmb: maintain font size; shift 16 bit fixed 8 bits to become 32 bit
02102     */
02103     
02104     WSRec *ws;
02105     TextBlock *block;
02106     FormatRec *format;
02107     char *pdata;
02108     long ctblocks, ctformats, ctbytes, ctchars;
02109     shape_ref visarea, pagearea;
02110     Rect r;
02111     
02112     // start by pointing to all of the relevant structures
02113     lockhandle (hpacked);
02114     
02115     ws = (WSRec *) *hpacked;
02116     
02117     block = (TextBlock *) ((char *) ws + sizeof (WSRec));
02118     
02119     format = (FormatRec *) ((char *) block + conditionallongswap ((long) (*ws).tHandle));
02120     
02121     pdata = (char *) format + conditionallongswap ((long) (*ws).tFormat);
02122     
02123     // create paige record
02124     
02125     diskrecttorect (&(*ws).tRect, &r);
02126 
02127     visarea = newshape (&r);
02128     
02129     pagearea = newlongshape (&(*ws).tBounds);
02130     
02131     PG_TRY (&mem_globals) {
02132     
02133         *pg = pgNew (&ws_globals, USE_NO_DEVICE, visarea, pagearea, MEM_NULL, defaultpgflags);
02134         }
02135     PG_CATCH {
02136     
02137         pgFailureDispose (*pg);
02138         
02139         memoryerror ();
02140         }
02141     PG_ENDTRY;
02142     
02143     pgDisposeShape (visarea);
02144     
02145     pgDisposeShape (pagearea);
02146     
02147     // loop through text blocks, retaining character data, skipping the rest
02148     
02149     ctblocks = conditionallongswap ((long) (*ws).tHandle) / sizeof (TextBlock);
02150     
02151     for  ( ; --ctblocks >= 0; ++block) {
02152         
02153         ctbytes = conditionallongswap ((long) (*block).TBHandle);
02154         
02155         ctchars = ctbytes;
02156 
02157         if (ctblocks == 0)
02158             ctchars -= 2;
02159 
02160         pgInsert (*pg, (pg_byte_ptr) pdata, ctchars, CURRENT_POSITION, data_insert_mode, 0, draw_none);
02161         
02162         pdata += ctbytes;
02163         
02164         pdata += conditionallongswap ((long) (*block).TBLines);
02165         
02166         pdata += conditionallongswap ((long) (*block).TBCtl);
02167         }
02168     
02169     // loop through formats
02170     
02171     ctformats = conditionallongswap ((long) (*ws).tFormat) / sizeof (FormatRec);
02172     
02173     for ( ; --ctformats >= 0; ++format) {
02174         font_info   font, fontmask;
02175         style_info  style, stylemask;
02176         select_pair range;
02177 
02178         pgFillBlock (&font, sizeof(font_info), 0);
02179         pgFillBlock (&fontmask, sizeof(font_info), SET_MASK_BITS);
02180         
02181         pgBlockMove ((*format).fName, font.name, stringsize ((*format).fName));
02182         
02183         pgFillBlock (&stylemask, sizeof (style_info), 0);
02184         stylemask.point = SET_MASK_BITS;
02185         style.point = FixRound ((*format).fPoint);
02186         style.point <<= 8;
02187         
02188         pgFillBlock(stylemask.styles, (short) condense_var * sizeof(short), SET_MASK_BITS);
02189         QDStyleToPaige(conditionalshortswap ((*format).fStyle), &style);
02190         
02191         range.begin = conditionallongswap ((*format).Pos);
02192         
02193         if (ctformats > 0)
02194             range.end = conditionallongswap ((*(format + 1)).Pos);
02195         else
02196             range.end = min (pgTextSize (*pg), conditionallongswap ((*ws).tLength) - 1);
02197         
02198         pgSetStyleAndFont (*pg, &range, &style, &stylemask, &font, &fontmask, draw_none);
02199         }
02200     
02201     if (true) {
02202         
02203         rulerRecord *ruler;
02204         long rulerinfolen, ctrulers;
02205         
02206         if (odd ((long) pdata))
02207             ++pdata;
02208         
02209         rulerinfolen = gethandlesize (hpacked) - (pdata - (char *) ws);
02210         
02211         ruler = (rulerRecord *) (pdata + rulerheaderlen);
02212         
02213         ctrulers = (rulerinfolen - rulerheaderlen) / sizeof (rulerRecord);
02214         
02215         for ( ; --ctrulers >= 0; ++ruler) {
02216             par_info info, mask;
02217             select_pair range;
02218             
02219             pgFillBlock(&info, sizeof(par_info), 0);
02220             pgInitParMask(&mask, 0);
02221             
02222             info.justification = conditionalshortswap ((*ruler).just);
02223             mask.justification = SET_MASK_BITS;
02224             
02225         //  info.leading_extra = (*ruler).spacing;
02226         //  mask.leading_extra = SET_MASK_BITS;
02227             
02228         //  can also do left/right margins, para indent, tabs, etc.
02229         
02230             range.begin = conditionallongswap ((*ruler).rBegin);
02231             
02232             if (ctrulers > 0)
02233                 range.end = conditionallongswap ((*(ruler + 1)).rBegin);
02234             else
02235                 range.end = conditionallongswap ((*ws).tLength) - 1;
02236             
02237             pgSetParInfo (*pg, NULL, &info, &mask, draw_none);
02238             }
02239         }
02240     
02241     unlockhandle (hpacked);
02242     
02243     return (true);
02244     } /*unpackwordsolutionenginefile*/
02245 
02246 
02247 static boolean wpunpacktext (Handle hpacked, pg_ref *pg) {
02248     
02249     /*
02250     12/26/91 dmb: call memoryerror on HandleToWS failure
02251     */
02252     
02253     file_ref filemap;
02254     long position;
02255     pg_byte *ptext;
02256     long len = gethandlesize (hpacked);
02257     pg_error ec;
02258     
02259     filemap = MemoryAlloc (&mem_globals, sizeof (pg_byte), len, 0);
02260     
02261     ptext = (pg_byte *) UseMemory (filemap);
02262     
02263     pgBlockMove (*hpacked, ptext, len);
02264     
02265     UnuseMemory (filemap);
02266     
02267     position = 0;
02268     
02269     ec = pgVerifyFile (filemap, pgScrapMemoryRead, position);
02270     
02271     if (ec != 0) {
02272         
02273         if (unpackwordsolutionenginefile (hpacked, pg))
02274             ec = noErr;
02275         }
02276     else {
02277         
02278         PG_TRY (&mem_globals) {
02279             
02280             *pg = pgNewShell (&ws_globals);
02281             
02282             ec = pgReadDoc (*pg, &position, NULL, 0, pgScrapMemoryRead, filemap);
02283             
02284             if (ec == noErr)
02285                 pgSetHiliteStates (*pg, deactivate_verb, no_change_verb, false);
02286             }
02287         PG_CATCH {
02288             pgFailureDispose (*pg);
02289             
02290             memoryerror ();
02291         }
02292         PG_ENDTRY;
02293         }
02294     
02295     DisposeMemory (filemap);
02296         
02297     return (ec == noErr);
02298     } /*wpunpacktext*/
02299 
02300 
02301 static boolean wppackheader (long buffersize, Handle *hpacked) {
02302     
02303     tywpheader header;
02304     register Handle h;
02305     register hdlwprecord hwp = wpdata;
02306     
02307     *hpacked = nil; /*default returned value*/
02308     
02309     if (!newclearhandle (sizeof (tywpheader), hpacked))
02310         return (false);
02311     
02312     clearbytes (&header, sizeof (header)); /*assure all bits set to 0*/
02313     
02314     header.versionnumber = conditionalshortswap (1);
02315     
02316     /*timestamp (&header.timelastsave);*/ /*dmb 4.1b13: don't stamp it; wpdirty sets it as true mode date*/
02317     
02318     header.timecreated = conditionallongswap ((**hwp).timecreated);
02319     
02320     header.timelastsave = conditionallongswap ((**hwp).timelastsave);
02321     
02322     header.ctsaves = ++(**hwp).ctsaves;
02323     
02324     wpgetmaxpos (&header.maxpos);
02325     
02326     /* can not use other macros while using ++ or as a parameter to a function*/
02327     memtodisklong (header.ctsaves);
02328     memtodisklong (header.maxpos);
02329     
02330     header.flags |= floneline_mask * (**hwp).floneline;
02331     
02332     header.flags |= flruleron_mask * (**hwp).flshowruler;
02333     
02334     /*
02335     header.flexpandvariables = (**hwp).flexpandvariables;
02336     
02337     header.flhilitevariables = (**hwp).flhilitevariables;
02338     */
02339     
02340     recttodiskrect (&(**hwp).windowrect, &header.windowrect);
02341     
02342     header.buffersize = conditionallongswap (buffersize);
02343     
02344     header.varlistsize = 0;
02345     
02346     h = *hpacked; /*copy into register*/
02347     
02348     moveleft (&header, *h, sizeof (header));
02349     
02350     return (true);
02351     } /*wppackheader*/
02352 
02353 
02354 static boolean wppacktext (pg_ref pg, Handle *hpacked) {
02355     
02356     /*
02357     12/26/91 dmb: call memoryerror on WSToHandle failure
02358     
02359     4.16.97 dmb: was passing wpbuffer to pgSaveDoc instead of pg parameter.
02360 
02361     5.0a10 dmb: call pgTerminateFile, so we're not crashed by extra, trailing data
02362     */
02363     
02364     file_ref filemap;
02365     long pos;
02366     pg_byte *ptext;
02367     long len;
02368     boolean fl;
02369     
02370     filemap = (file_ref) MemoryAlloc (&mem_globals, sizeof (pg_byte), 0, 0);
02371     
02372     pos = 0;
02373     
02374     fl = (pgSaveDoc (pg, &pos, NULL, 0, pgScrapMemoryWrite, filemap, 0) == 0);
02375     
02376     // dmb: for future: pgSaveAllEmbedRefs (pg, pgScrapMemoryWrite, NULL, &pos, filemap);
02377     
02378     if (fl)
02379         fl = (pgTerminateFile (pg, &pos, pgScrapMemoryWrite, filemap) == 0);
02380 
02381     if (fl) {
02382     
02383         ptext = (pg_byte *) UseMemory(filemap);
02384         
02385         len = GetMemorySize (filemap);
02386         
02387         fl = newfilledhandle (ptext, len, hpacked);
02388         }
02389     
02390     UnuseAndDispose ((memory_ref) filemap);
02391 
02392     if (!fl)
02393         memoryerror ();
02394     
02395     return (fl);
02396     } /*wppacktext*/
02397 
02398 
02399 boolean wppack (Handle *hpacked) {
02400     
02401     /*
02402     dmb 9/6/90:  "header" is now really a "trailer".  since the header record 
02403     is never very large, while the packed wp can be huge, sticking the 
02404     header on the end is less memory intensive
02405     */
02406     
02407     Handle hpackedtext, hpackedheader;
02408     register boolean fl = false;
02409     long buffersize;
02410     
02411     *hpacked = nil;
02412     
02413     if (!wpsetglobals ())
02414         return (false);
02415     
02416     if (!wppacktext (wpbuffer, &hpackedtext))
02417         return (false);
02418     
02419     buffersize = gethandlesize (hpackedtext);
02420     
02421     if (!wppackheader (buffersize, &hpackedheader)) {
02422         
02423         disposehandle (hpackedtext);
02424         
02425         return (false);
02426         }
02427     
02428     fl = pushhandle (hpackedheader, hpackedtext);
02429     
02430     disposehandle (hpackedheader);
02431     
02432     *hpacked = hpackedtext;
02433     
02434     return (fl);
02435     } /*wppack*/
02436 
02437 
02438 boolean wpunpack (Handle hpacked, hdlwprecord *hwp) {
02439     
02440     /*
02441     unpack the packed edit record stored in the handle into wpdata.
02442     
02443     we fit the text to the current window (wpwindow) and its associated
02444     information record (wpwindowinfo).
02445     
02446     6/6/90 DW: we no longer dispose of the packed handle.  should we dispose
02447     of it if there was an error?  no, it should be up to the caller to get
02448     rid of the packed handle.  it means our memory "high water mark" is a little
02449     higher -- but confusion over this cost us three days of debugging (gotta 
02450     admit I was a little hazy, shouldn't have taken that long.  anyway...)
02451 
02452     5.0b9 dmb: don't smash wpbuffer global
02453     */
02454     
02455     register ptrwprecord pwp;
02456     tywpheader header;
02457     bigstring bsname;
02458     Rect r;
02459     tywpflags flags;
02460     
02461     /*remove "header" from end of packed wsdata, so we can pass remainder to wpnew*/
02462 
02463     if (!popfromhandle (hpacked, sizeof (header), &header))
02464         goto error;
02465 
02466     disktomemlong (header.buffersize);
02467 
02468     sethandlesize (hpacked, header.buffersize);
02469     
02470     setemptystring (bsname); /*zero-length name*/
02471     
02472 //  setrect (&rclip, -infinity, -infinity, infinity, infinity); /*wide open clip*/
02473     
02474     diskrecttorect (&header.windowrect, &r);
02475     
02476     flags = wpnoflags;
02477     
02478     if ((header.flags & floneline_mask) != 0)
02479         flags |= wponeline;
02480     
02481     *hwp = wpnewbuffer (hpacked, &r, &shellprintinfo.paperrect, flags, false);
02482     
02483     if (*hwp == nil)
02484         return (false);
02485     
02486     pwp = **hwp; /*move into register*/
02487     
02488     wpsetavailbounds ((pg_ref) (*pwp).wpbuffer); /*adjust bounds for current page setup*/
02489     
02490     (*pwp).timecreated = conditionallongswap (header.timecreated);
02491     
02492     (*pwp).timelastsave = conditionallongswap (header.timelastsave);
02493     
02494     (*pwp).ctsaves = conditionallongswap (header.ctsaves);
02495     
02496     assert ((*pwp).floneline == ((header.flags & floneline_mask) != 0));
02497     
02498     (*pwp).flshowruler = (header.flags & flruleron_mask) != 0;
02499     
02500     /*
02501     (*pwp).flexpandvariables = header.flexpandvariables;
02502     
02503     (*pwp).flhilitevariables = header.flhilitevariables;
02504     */
02505     
02506     diskrecttorect (&header.windowrect, &(*pwp).windowrect);
02507     
02508     return (true);
02509     
02510     error:
02511         shellerrormessage (BIGSTRING ("\x43" "Can't unpack wptext object because unexpected data was encountered."));
02512 
02513         return (false);
02514     } /*wpunpack*/
02515 
02516 
02517 boolean wpgetpackedmaxpos (Handle hpacked, long *maxpos) {
02518     
02519     /*
02520     extract the saved maxpos from the packed wp header
02521     */
02522     
02523     register Handle h = hpacked;
02524     long ix;
02525     tywpheader header;
02526     
02527     ix = gethandlesize (h) - sizeof (header);
02528     
02529     if (!loadfromhandle (h, &ix, sizeof (header), &header))
02530         return (false);
02531     
02532     assert (sizeof (tyOLD42wpheader) == sizeof (tywpheader));
02533     
02534     *maxpos = conditionallongswap (header.maxpos);
02535     
02536     return (true);
02537     } /*wpgetpackedmaxpos*/
02538 
02539 
02540 static long gettextlength (pg_ref pg) {
02541 
02542     return (pgTextSize (pg));
02543     } /*gettextlength*/
02544 
02545 
02546 static boolean wpnormalizelineendings (Handle htext) {
02547     
02548     /*
02549     5.1.4 dmb: convert any lf-only endings to cr-lf
02550     */
02551     
02552     handlestream s;
02553     byte ch, chlast = chnul;
02554     byte bscr[] = "\x01\r";
02555     
02556     openhandlestream (htext, &s);
02557     
02558     while (!athandlestreameof (&s)) {
02559         
02560         ch = nexthandlestreamcharacter (&s);
02561         
02562         if ((ch == chlinefeed) && (chlast != chreturn)) {
02563         
02564             if (!mergehandlestreamstring (&s, 0, bscr))
02565                 return (false);
02566             }
02567         
02568         chlast = ch;
02569         
02570         ++s.pos;
02571         }
02572     
02573     closehandlestream (&s);
02574     
02575     return (true);
02576     } /*wpnormalizelineendings*/
02577 
02578 
02579 boolean wpgettexthandle (Handle *htext) {
02580     
02581     /*
02582     return in htext a handle containing the entire text of the current wp.
02583     
02584     12/26/91 dmb: call memoryerror on WSGetText failure
02585     
02586     dmb 12/5/96: paige
02587     */
02588     
02589     Handle          h;
02590     paige_rec_ptr   pg_rec;
02591     pg_byte_ptr     text;
02592     text_block_ptr  block;
02593     long            num_blocks;
02594     long            text_size;
02595     long            total_bytes = 0;
02596     boolean         fl = true;  
02597     
02598     if (!wpsetglobals ()) 
02599         return (false);
02600     
02601     if (!newemptyhandle (&h))
02602         return (false);
02603 
02604     pg_rec = (paige_rec_ptr) UseMemory (wpbuffer);
02605 
02606     block = (text_block_ptr) UseMemory (pg_rec->t_blocks);
02607     
02608     for (num_blocks = GetMemorySize (pg_rec->t_blocks); fl && (--num_blocks >= 0); ) {
02609 
02610         text_size = GetMemorySize (block->text);
02611 
02612         text = (pg_byte_ptr) UseMemory (block->text);
02613         
02614         total_bytes += text_size;
02615 
02616         fl = enlargehandle (h, text_size, text);
02617         
02618         UnuseMemory (block->text);
02619 
02620         ++block;
02621         }
02622     
02623     UnuseMemory (pg_rec->t_blocks);
02624     
02625     UnuseMemory (wpbuffer);
02626     
02627     #ifdef xxxWIN95VERSION
02628         if (fl)
02629             fl = wpcr2crlf (h);
02630     #endif
02631     
02632     if (fl)
02633         *htext = h;
02634     else    
02635         disposehandle (h);
02636     
02637     return (fl);
02638     } /*wpgettexthandle*/
02639 
02640 
02641 boolean wpgettext (bigstring bs, long *cttotal) {
02642     
02643     /*
02644     return the text as a string, truncated if necessary.  in cttotal, return 
02645     the total number of characters in the text.
02646     */
02647     
02648     Handle htext;
02649     
02650     setemptystring (bs); /*default, in case of error*/
02651     
02652     if (!wpgettexthandle (&htext))
02653         return (false);
02654     
02655     *cttotal = gethandlesize (htext);
02656     
02657     texthandletostring (htext, bs);
02658     
02659     disposehandle (htext);
02660     
02661     return (true);
02662     } /*wpgettext*/
02663 
02664 
02665 boolean wpgetseltexthandle (Handle *htext) {
02666     
02667     /*
02668     9/27/91 dmb: return in htext a handle containing the currently selected text.
02669     
02670     dmb 12/5/96: paige
02671 
02672     5.0a16: return empty handle if pgCopyText returns null. For an empty selection
02673     Win does this, but the Mac does something else.
02674     */
02675     
02676     text_ref text;
02677 
02678     if (!wpsetglobals ())
02679         return (false);
02680     
02681     text = pgCopyText (wpbuffer, NULL, all_visible_text_chars);
02682     
02683     if (text == MEM_NULL)
02684         newemptyhandle (htext);
02685     
02686     else {
02687     
02688         newfilledhandle (UseMemory (text), GetMemorySize (text), htext);
02689         
02690         UnuseAndDispose ((memory_ref) text);
02691 
02692         #ifdef xxxWIN95VERSION
02693             if (htext != nil)
02694                 wpcr2crlf (*htext);
02695         #endif
02696         }
02697     
02698     return (*htext != nil);
02699     } /*wpgetseltexthandle*/
02700 
02701 
02702 boolean wpgetseltext (bigstring bs) {
02703     
02704     Handle htext;
02705     
02706     setemptystring (bs); /*default return*/
02707     
02708     if (!wpgetseltexthandle (&htext))
02709         return (false);
02710     
02711     texthandletostring (htext, bs);
02712     
02713     disposehandle (htext);
02714     
02715     return (true);
02716     } /*wpgetseltext*/
02717 
02718 
02719 boolean wppreedit (void);  //forward
02720 
02721 void wppostruleredit (boolean, boolean); //forward
02722 
02723 boolean wppushundo (long, void *); // forward
02724 
02725 
02726 #define PGINSERT_BLOCKSIZE 2048
02727 
02728 static boolean wpinserttexthandle (pg_ref pg, Handle htext, short draw_mode, boolean flsetupundo) {
02729 
02730     /*
02731     5.1.4 dmb: normalize the line endings. Note: we're modifying the input parameter
02732     */
02733     
02734     handlestream s;
02735     memory_ref textbuf;
02736     byte *pbuf;
02737 
02738     if (!wpnormalizelineendings (htext))
02739         return (false);
02740     
02741     PG_TRY (&mem_globals)
02742     {
02743         openhandlestream (htext, &s);
02744         
02745         if (flsetupundo) {
02746             
02747             pushundoaction (undopastestring);
02748             
02749             wppushundo (undo_insert, (void *) &s.eof);
02750             }
02751         
02752         textbuf = MemoryAlloc (&mem_globals, sizeof (pg_byte), PGINSERT_BLOCKSIZE, 0);
02753         
02754         pbuf = (pg_byte *) UseMemory (textbuf);
02755         
02756         while (!athandlestreameof (&s)) {
02757              
02758             long ctbytes = min (PGINSERT_BLOCKSIZE, s.eof - s.pos);
02759 
02760             boolean flhashtmlstyles = false;
02761             
02762             if (!readhandlestream (&s, pbuf, ctbytes))
02763                 break;
02764             
02765             //#ifdef PIKE
02766                 if (outlinedata != NULL)
02767                     if ((**outlinedata).flhtml)
02768                             flhashtmlstyles = wpapplyhtmlstyles (htext, (unsigned long)NULL, false);
02769             //#endif
02770 
02771             if (flhashtmlstyles) {
02772         
02773                 pgInsert (pg, (pg_byte_ptr) pbuf, ctbytes, CURRENT_POSITION, data_insert_mode, 0, draw_none);
02774             
02775                 wpapplyhtmlstyles (htext, pg, draw_mode);
02776                 } /*if*/
02777 
02778             else {
02779 
02780                 pgInsert (pg, (pg_byte_ptr) pbuf, ctbytes, CURRENT_POSITION, data_insert_mode, 0, draw_mode);
02781 
02782                 } /*else*/
02783 
02784         //  pgInsertText (pg, (pg_byte_ptr) pbuf, ctbytes, NULL, NULL, NULL, draw_mode);
02785 
02786 
02787 
02788             } /*while*/
02789         UnuseAndDispose (textbuf);
02790         
02791         closehandlestream (&s);
02792 
02793         return (true);
02794         }
02795     PG_CATCH
02796     {
02797         #ifdef MACVERSION
02798             oserror (memFullErr);
02799         #endif
02800         #ifdef WIN95VERSION
02801             oserror (ERROR_OUTOFMEMORY);
02802         #endif
02803         
02804         return (false);
02805     }
02806     PG_ENDTRY;
02807     } /*wpinserttexthandle*/
02808 
02809 
02810 boolean wpsettexthandle (Handle htext) {
02811     
02812     /*
02813     9/28/91 dmb: cut away all of the existing text before setting 
02814     the new so that all format runs go away.
02815     
02816     12/26/91 dmb: make sure undo is cleared
02817     
02818     dmb 12/5/96: paige
02819     
02820     5.0.2b17 dmb: added PG_TRY block
02821     */
02822     
02823     select_pair range;
02824     boolean fl = false;
02825     
02826     if (!wppreedit ())
02827         return (false);
02828     
02829     if (wpownwindowinfo ())
02830         pushundoaction (0); /*can't undo this*/
02831     
02832     range.begin = 0; range.end = gettextlength (wpbuffer);
02833     
02834     pgDelete (wpbuffer, &range, draw_none);
02835     
02836     if (htext != nil)
02837         fl = wpinserttexthandle (wpbuffer, htext, wpdisplay_way, false);
02838     
02839     wpdirtyselectioninfo ();
02840     
02841     wppostruleredit (fl, fl);
02842     
02843     return (fl);
02844     } /*wpsettexthandle*/
02845 
02846 
02847 boolean wpsettext (bigstring bs) {
02848     
02849     Handle htext;
02850     boolean fl;
02851     
02852     if (!newtexthandle (bs, &htext))
02853         return (false);
02854     
02855     fl = wpsettexthandle (htext);
02856     
02857     disposehandle (htext);
02858     
02859     return (fl);
02860     } /*wpsettext*/
02861 
02862 
02863 static void wpnoop (void) {
02864     
02865     } /*wpnoop*/
02866 
02867 
02868 hdlwprecord wpnewbuffer (Handle hpacked, const Rect *rclip, const Rect *rbounds, tywpflags wpflags, boolean flinwindow) {
02869     
02870     /*
02871     12/26/91 dmb: call memoryerror on WSNew failure
02872     
02873     4.0b7 dmb: initialize timelastsave to creation time; it's really a modification date.
02874 
02875     5.0b9 dmb: don't use (smash) wpbuffer global for what's really a local var
02876     */
02877     
02878     Handle hrecord;
02879     register hdlwprecord hwp;
02880     long flags;
02881 //  tyconfigrecord config;
02882     shape_ref visarea, pagearea;
02883 //  generic_var device = flinwindow? MEM_NULL : USE_NO_DEVICE;
02884     generic_var device = USE_NO_DEVICE;
02885     pg_ref hbuf = nil;
02886     
02887     if (flinwindow)
02888     {
02889         #if TARGET_API_MAC_CARBON == 1
02890         device = (generic_var)GetWindowPort(wpwindow);
02891         #else
02892         device = (generic_var) wpwindow;
02893         #endif
02894     }
02895     
02896     if (!newclearhandle (sizeof (tywprecord), &hrecord))
02897         return (nil);
02898     
02899     hwp = (hdlwprecord) hrecord; /*copy into register*/
02900     
02901     (**hwp).floneline = (wpflags & wponeline) != 0;
02902     
02903     (**hwp).flalwaysmeasuretext = (wpflags & wpalwaysmeasure) != 0;
02904     
02905     (**hwp).wprect = *rclip;
02906     
02907     if (hpacked) /*we have a packed version to go with*/ {
02908         
02909         if (wpunpacktext (hpacked, &hbuf))
02910             ;   // *** set area???
02911         }
02912     else {
02913         
02914         flags = defaultpgflags;
02915         
02916         if ((wpflags & wponeline) != 0)
02917             flags |= NO_WRAP_BIT; // | EXTERNAL_SCROLL_BIT));
02918         
02919         visarea = newshape (rclip);
02920         
02921         pagearea = newshape (rbounds);
02922     
02923         setdefaultstyles ((wpflags & wpprinting) != 0);
02924         
02925         PG_TRY (&mem_globals) {
02926         
02927             hbuf = pgNew (&ws_globals, device, visarea, pagearea, MEM_NULL, flags);
02928             }
02929         PG_CATCH {
02930         
02931             pgFailureDispose (hbuf);
02932             
02933             memoryerror ();
02934             }
02935         PG_ENDTRY;
02936         
02937         pgDisposeShape (visarea);
02938         
02939         pgDisposeShape (pagearea);
02940         }
02941     
02942     if (hbuf == nil) { /*memory error*/
02943             
02944         disposehandle ((Handle) hwp);
02945         
02946         return (nil);
02947         }
02948     
02949     pgSetHiliteStates (hbuf, activate_verb, activate_verb, false);
02950     
02951 //  pgSetPointSize (hbuf, (**wpwindowinfo).selectioninfo.fontsize, NULL, false);
02952     
02953     /*don't let Paige autoscroll; it goes too fast and doesn't update scroll bars*/ {
02954 
02955         wpsetautoscroll (hbuf, false);
02956         }
02957     
02958     if ((wpflags & wpneverscroll) != 0)
02959         (**hwp).flneverscroll = true;
02960     else
02961         pgSetScrollParams (hbuf, 32, 0, 0, 0);
02962     
02963     (**hwp).wpbuffer = (Handle) hbuf;
02964     
02965     (**hwp).timecreated = (**hwp).timelastsave = timenow ();
02966     
02967     (**hwp).dirtyroutine = &wpnoop;
02968     
02969     //#if ACCESSOR_CALLS_ARE_FUNCTIONS == 1
02970     //Code change by Timothy Paustian Sunday, May 7, 2000 10:52:06 PM
02971     //Changed to Opaque call for Carbon
02972     //in carbon you don't need UPPs so just install the callback
02973     //(**hwp).trackclickroutine = wptrackclick;
02974     //#else
02975     (**hwp).trackclickroutine = wptrackclickUPP; 
02976     //#endif
02977     (**hwp).preeditroutine = &truenoop;
02978     
02979     (**hwp).posteditroutine = &wpnoop;
02980     
02981     (**hwp).setscrollbarsroutine = &wpnoop;
02982     
02983     return (hwp);
02984     } /*wpnewbuffer*/
02985 
02986 
02987 boolean wpnewrecord (Rect r, hdlwprecord *hwprecord) {
02988 #pragma unused (r)
02989 
02990     /*
02991         3.0.4b8 dmb: set the scratchport
02992     */
02993     
02994     bigstring bs;
02995     tyconfigrecord lconfig;
02996     register hdlwprecord hwp;
02997     Rect rclip;
02998     
02999     setemptystring (bs);
03000     
03001     shellgetconfig (idwpconfig, &lconfig);
03002     
03003     pushscratchport ();
03004     
03005     pushstyle (lconfig.defaultfont, lconfig.defaultsize, lconfig.defaultstyle);
03006     
03007     rclip = lconfig.defaultwindowrect;
03008 
03009     offsetrect (&rclip, -rclip.left, -rclip.top);
03010 
03011     hwp = wpnewbuffer (nil, &rclip, &shellprintinfo.paperrect, 0, false);
03012     
03013     popstyle ();
03014     
03015     popport ();
03016     
03017     if (hwp == nil)
03018         return (false);
03019     
03020     (**hwp).windowrect = lconfig.defaultwindowrect;
03021     
03022     (**hwp).fldirty = true;
03023     
03024     *hwprecord = hwp;
03025     
03026     return (true);
03027     } /*wpnewrecord*/
03028 
03029 
03030 void wpdisposerecord (hdlwprecord hwp) {
03031     
03032     register pg_ref hbuf = (pg_ref) (**hwp).wpbuffer;
03033     
03034     if (hbuf != nil)
03035         pgDispose (hbuf);
03036     
03037     disposehandle ((Handle) (**hwp).hname);
03038     
03039     wpdisposeundo (hwp);
03040     
03041     disposehandle ((Handle) hwp);
03042     } /*wpdisposerecord*/
03043 
03044 
03045 void wpdispose (void) {
03046     
03047     if (!wpsetglobals ())
03048         return;
03049     
03050     wpresettyping ();
03051     
03052     wpdisposerecord (wpdata);
03053     
03054     wpdata = nil;
03055     } /*wpdispose*/
03056 
03057 
03058 #ifdef MACVERSION
03059 #pragma mark === editing ===
03060 #endif
03061 
03062 
03063 boolean wppreedit (void) {
03064     
03065     /*
03066     5.0b8 dmb: resize area bounds here, now in postedit, so mouse
03067     operations benefit immmediately
03068     */
03069     
03070     register hdlwprecord hwp = wpdata;
03071     
03072     if (!wpsetglobals ())
03073         return (false);
03074     
03075     if (!(*(**hwp).preeditroutine) ())
03076         return (false);
03077     
03078     wppushdraw ();
03079 
03080     (**hwp).fltextchanged = false; /*on last edit operation, text did not change, by default*/
03081     
03082     ++(**hwp).fleditingnow;
03083     
03084     return (true);
03085     } /*wppreedit*/
03086 
03087 
03088 void wppostruleredit (boolean flchangedtext, boolean flvisi) {
03089     
03090     /*
03091     high-resolution postedit, after using rulers add-on package calls that 
03092     return the index of the first line requiring recalc
03093     
03094     12/6/96 dmb: new code for paige
03095 
03096     5.0a5 dmb: fixed up new auto bounds expansion code. don't make bounds
03097     narrower than the visible area
03098     */
03099     
03100     register boolean fldisplay = wpdisplayenabled ();
03101     register hdlwprecord hwp = wpdata;
03102     
03103     --(**hwp).fleditingnow;
03104     
03105     if (flchangedtext)
03106         (**hwp).fltextchanged = true;
03107     
03108     if (fldisplay) {
03109         
03110         wpadjustboundstofit ();
03111         
03112         wpresetscrollbars ();
03113         
03114         if (flvisi)
03115             wpcheckscrollpos (); /*make sure we have shrunk out of scroll range*/
03116         
03117         wpdirty (flchangedtext);
03118         
03119         if (wpwindowinfo != nil)
03120             (**wpwindowinfo).selectioninfo.fldirty = true;
03121         
03122         if (flvisi)
03123             wpvisicursor ();
03124         }
03125     else {
03126         
03127         if (flchangedtext)
03128             (**hwp).fldirty = true;
03129         else
03130             (**hwp).fldirtyview = true;
03131         }
03132     
03133     wppopdraw ();
03134     
03135     (*(**hwp).posteditroutine) ();
03136     } /*wppostruleredit*/
03137 
03138 
03139 void wppostedit (boolean flrecalc) {
03140     
03141     /*
03142     low-resolution postedit, after using standard ws-engine calls that 
03143     only return true or false for recalc.
03144     */
03145     
03146     wppostruleredit (flrecalc, true);
03147     } /*wppostedit*/
03148 
03149 
03150 /*
03151 static pascal boolean wperrorhandler (long ctbytesneeded) {
03152     
03153     return (false);
03154     } /%wperrorhandler%/
03155 */
03156 
03157 
03158 static void setupundo (long undocode, void *insertref) {
03159     
03160     undo_ref undo = getundo ();
03161     
03162     switch (undocode) {
03163     
03164         case undo_none: // probably a Copy
03165             pgDisposeUndo (undo);
03166             
03167             setundo (MEM_NULL);
03168             
03169             break;
03170         
03171         case undo_typing:
03172         case undo_fwd_delete:
03173         case undo_backspace:
03174             setundo (pgPrepareUndo (wpbuffer, undocode, (void *) undo));
03175             
03176             break;
03177         
03178         default:
03179             pgDisposeUndo (undo);
03180             
03181             setundo (pgPrepareUndo (wpbuffer, undocode, insertref));
03182 
03183             break;
03184         }
03185     } /*setupundo*/
03186 
03187 
03188 static boolean wppushundostep (void); // forward;
03189 
03190 
03191 static boolean wpundoroutine (Handle hdata, boolean flundo) {
03192     
03193     /*
03194     12/6/96 dmb: paige implementation
03195     */
03196     
03197     undo_ref hundo = (undo_ref) hdata;
03198     
03199     if (flundo) {
03200         
03201         assert (getundo () == nil);
03202         
03203         setundo (hundo);
03204         
03205         wpundo ();
03206         
03207         wppushundostep ();
03208         }
03209     else {
03210         
03211         if (wpdata && (**wpdata).fleditingnow)
03212             setundo (hundo); // wp owns it now
03213         else
03214             pgDisposeUndo (hundo);
03215         }
03216     
03217     return (true);
03218     } /*wpundoroutine*/
03219 
03220 
03221 static boolean wppushundostep (void) {
03222     
03223     /*
03224     12/6/96 dmb: paige implementation. we just need to be called 
03225     so we can ask paige to do the undo.
03226     */
03227     
03228     if (!pushundostep (&wpundoroutine, (Handle) getundo ()))
03229         return (false);
03230     
03231     setundo (nil); // undo owns it now
03232     
03233     return (true);
03234     } /*wppushundostep*/
03235 
03236 
03237 boolean wppushundo (long undocode, void *insertref) {
03238     
03239     setupundo (undocode, insertref);
03240     
03241     return (wppushundostep ());
03242     } /*wppushundo*/
03243 
03244 
03245 static boolean wppushrulerundo (void) {
03246     
03247     return (wppushundo (undo_format, NULL));
03248     } /*wppushrulerundo*/
03249 
03250 
03251 boolean wppushformatundo (void) {
03252     
03253     return (wppushrulerundo ());
03254     } /*wppushformatundo*/
03255 
03256 
03257 static boolean wpsetcaretpos (pg_short_t caretverb) {
03258     
03259     /*
03260     5.0a16 dmb: fart around to get selection to work right when going home, 
03261     end-of-line, etc. Paige stops at the edge of the visible area otherwise.
03262     */
03263 
03264     boolean flwordwise = (caretverb == next_word_caret || caretverb == previous_word_caret);
03265     boolean flextend = keyboardstatus.flshiftkey;
03266     long oldstartsel, oldendsel;
03267     long newstartsel, newendsel;
03268 
03269     if (flextend)
03270     {
03271         if (flwordwise)
03272             caretverb |= EXTEND_CARET_FLAG;
03273         else
03274             pgGetSelection (wpbuffer, &oldstartsel, &oldendsel);
03275     }
03276 
03277     pgSetCaretPosition (wpbuffer, caretverb, true);
03278     
03279     if (flextend && !flwordwise) {
03280         
03281         pgGetSelection (wpbuffer, &newstartsel, &newendsel);
03282 
03283         pgSetSelection (wpbuffer, oldstartsel, newendsel, 0, true);
03284         }
03285     
03286     return (true);
03287     } /*wpsetcaretpos*/
03288 
03289 
03290 boolean wptraversehiddentext (tydirection dir, long *newstartsel) {
03291     
03292     boolean flmoved = false;
03293     long oldstartsel, oldendsel;
03294     long stylebits, consistentbits;
03295 
03296     //#ifdef PIKE
03297     
03298         pgGetSelection (wpbuffer, &oldstartsel, &oldendsel);
03299 
03300         if (oldstartsel < 0)
03301             return (false); /*didn't move*/
03302 
03303         if (dir == left)
03304             *newstartsel = oldstartsel - 1;
03305         else
03306             *newstartsel = oldstartsel;
03307 
03308         while (true) {
03309 
03310             wpsetselection (*newstartsel, *newstartsel + 1);
03311 
03312             pgGetStyleBits (wpbuffer, &stylebits, &consistentbits);
03313 
03314             if (stylebits & 0x400) {
03315 
03316                 flmoved = true;
03317 
03318                 if ((*newstartsel == 0) && (dir == left))
03319 
03320                     break;
03321 
03322                 if (dir == left)
03323                     *newstartsel = *newstartsel - 1;
03324                 else
03325                     *newstartsel = *newstartsel + 1;
03326                 }
03327 
03328             else {
03329                 
03330                 if (dir == left)
03331                     *newstartsel = *newstartsel + 1;
03332 
03333                 break;
03334                 } /*else*/
03335             } /*while*/
03336         
03337         wpsetselection (*newstartsel, *newstartsel);
03338 
03339         if (!flmoved)
03340             wpsetselection (oldstartsel, oldendsel);
03341 
03342     //#endif
03343     
03344     return (flmoved);
03345     } /*wptraversehiddentext*/
03346 
03347 
03348 boolean wptrimhiddentext (void) {
03349     
03350     
03351     boolean fl = false;
03352     long startsel, endsel;
03353     long newstartsel, newendsel;
03354 
03355     //#ifdef PIKE
03356 
03357         wpgetselection (&startsel, &endsel);
03358 
03359         newstartsel = startsel;
03360 
03361         newendsel = endsel;
03362 
03363         wptraversehiddentext (right, &newstartsel);
03364 
03365         wpsetselection (endsel, endsel);
03366 
03367         wptraversehiddentext (left, &newendsel);
03368 
03369         wpsetselection (newstartsel, newendsel);
03370 
03371         if (startsel != newstartsel)
03372             fl = true;
03373 
03374         if (endsel != newendsel)
03375             fl = true;
03376         
03377     //#endif
03378     
03379     return (fl); /*the selection was trimmed*/
03380     } /*wptrimhiddentext*/
03381 
03382 
03383 /*boolean wptrimrighthiddentextfromselection (void) {
03384     
03385     #ifdef PIKE
03386     
03387         long startsel, endsel;
03388         long newendsel;
03389 
03390         wpgetselection (&startsel, &endsel);
03391 
03392         wpsetselection (endsel, endsel);
03393 
03394         if (wptraversehiddentext (left, &newendsel)) {
03395 
03396             wpsetselection (startsel, newendsel);
03397 
03398             return (true);
03399             }
03400 
03401         wpsetselection (startsel, endsel);
03402         
03403     #endif
03404     return (false); 
03405     } /%wptrimrighthiddentextfromselection%/
03406 */
03407 
03408 boolean wpkeystroke (void) {
03409     
03410     /*
03411     4.1b7 dmb: for forward delete keys, new WS needs a force recalc
03412     in case they come too fast & get buffered
03413 
03414     5.0b8 dmb: Windows-standard home/end, page up/down
03415     */
03416     
03417     pg_byte chkey = keyboardstatus.chkb;
03418     short modifiers = 0;
03419     boolean flinserting = true; 
03420     pg_short_t caretverb = (pg_short_t) -1;
03421     long undocode = undo_none;
03422     pg_short_t forcemotionverb = (pg_short_t) -1;
03423     long oldstartsel, oldendsel;
03424     long newstartsel, newendsel;
03425     #define null_caret ((pg_short_t) -1)
03426     boolean floptionkey = keyboardstatus.floptionkey;
03427     boolean flvisi = true;
03428     hdlwprecord pwpdata;
03429     
03430     #ifdef WIN95VERSION
03431         Point pt;
03432     #endif
03433     
03434     if (!wppreedit ())
03435         return (false);
03436     
03437     obscurecursor ();
03438     
03439     #ifdef WIN95VERSION
03440         if (keyboardstatus.flcmdkey) {
03441             
03442             floptionkey = true;
03443 
03444             keyboardstatus.flcmdkey = false;
03445             }
03446     #endif
03447 
03448     switch (chkey) {
03449     
03450         case chhome:
03451             #ifdef MACVERSION
03452                 caretverb = home_caret;
03453             #else
03454                 if (floptionkey)
03455                     caretverb = home_caret;
03456                 else
03457                     caretverb = begin_line_caret;
03458             #endif
03459             break;
03460         
03461         case chend:
03462             #ifdef MACVERSION
03463                 caretverb = doc_bottom_caret;
03464             #else
03465                 if (floptionkey)
03466                     caretverb = doc_bottom_caret;
03467                 else
03468                     caretverb = end_line_caret;
03469             #endif
03470             break;
03471         
03472         case chpageup:
03473             #ifdef WIN95VERSION
03474                 wpvisicursor ();
03475                 wpgetselpoint (&pt);
03476             #endif
03477             
03478             wpscroll (down, true, 1);
03479             
03480             #ifdef WIN95VERSION
03481                 wpsetselpoint (pt);
03482             #endif
03483             
03484             flinserting = flvisi = false;
03485             break;
03486         
03487         case chpagedown:
03488             #ifdef WIN95VERSION
03489                 wpvisicursor ();
03490                 wpgetselpoint (&pt);
03491             #endif
03492             
03493             wpscroll (up, true, 1);
03494             
03495             #ifdef WIN95VERSION
03496                 wpsetselpoint (pt);
03497             #endif
03498             
03499             flinserting = flvisi = false;
03500             break;
03501         
03502         case chuparrow:
03503             forcemotionverb = home_caret;
03504             
03505             if (floptionkey) {
03506                 #ifdef WIN95VERSION
03507                     wpscroll (down, false, 1);
03508                     flinserting = flvisi = false;
03509                 #else
03510                     caretverb = home_caret;
03511                 #endif
03512                 }
03513 
03514             if (keyboardstatus.flcmdkey)
03515                 caretverb = home_caret;
03516             break;
03517         
03518         case chdownarrow:
03519             forcemotionverb = doc_bottom_caret;
03520             
03521             if (floptionkey) {
03522                 #ifdef WIN95VERSION
03523                     wpscroll (up, false, 1);
03524                     flinserting = flvisi = false;
03525                 #else
03526                     caretverb = doc_bottom_caret;
03527                 #endif
03528                 }
03529             
03530             if (keyboardstatus.flcmdkey)
03531                 caretverb = doc_bottom_caret;
03532             break;
03533         
03534         case chleftarrow:
03535             if (floptionkey)
03536                 caretverb = previous_word_caret;
03537             
03538             if (keyboardstatus.flcmdkey)
03539                 caretverb = begin_line_caret;
03540             break;
03541         
03542         case chrightarrow:
03543             if (floptionkey)
03544                 caretverb = next_word_caret;
03545             
03546             if (keyboardstatus.flcmdkey)
03547                 caretverb = end_line_caret;
03548             break;
03549         
03550         case chdelete:
03551             undocode = undo_fwd_delete;
03552             break;
03553         
03554         case chbackspace: {
03555 
03556             long lnewstartsel;
03557 
03558             undocode = undo_backspace;
03559 
03560             wptraversehiddentext (left, &lnewstartsel);
03561 
03562             break;
03563             }
03564         
03565         default:
03566             flinserting = isprint (chkey) || (chkey == chtab) || (chkey == chreturn) || (chkey > 0x7F);
03567             
03568             if (flinserting)
03569                 undocode = undo_typing;
03570             
03571             break;
03572     }
03573     
03574     if (caretverb != null_caret) {
03575         
03576         wpsetcaretpos (caretverb);
03577         }
03578     
03579     else if (flinserting) {
03580         pwpdata = wpdata;
03581         
03582         if (undocode != undo_none) {
03583         
03584             pushundoaction (undotypingstring);
03585             
03586             //why this is needed or why it fixes the crashing bug I don't know but it does
03587             //rab 3/29/99
03588             
03589             wpdata = pwpdata;
03590             
03591 //          assert (pwpdata == wpdata);
03592             
03593             if (! ((*pwpdata)->flstartedtyping)) {
03594                 
03595                 wpdisposeundo (wpdata); // dispose any inherited undo after pushundoaction, before next statement
03596 
03597 //              assert (pwpdata == wpdata);
03598                 
03599                 (*pwpdata)->flstartedtyping = true;
03600                 }
03601             
03602 //          assert (pwpdata == wpdata);
03603 
03604             setupundo (undocode, NULL);
03605             
03606             wppushundostep ();
03607             }
03608         
03609         if (keyboardstatus.flshiftkey)
03610             modifiers |= EXTEND_MOD_BIT;
03611         
03612         if (forcemotionverb != null_caret)
03613             pgGetSelection (wpbuffer, &oldstartsel, &oldendsel);
03614         
03615         pgInsert (wpbuffer, &chkey, sizeof (pg_byte), CURRENT_POSITION, key_insert_mode, modifiers, wpdisplay_way);
03616         
03617         if (forcemotionverb != null_caret) {
03618             
03619             pgGetSelection (wpbuffer, &newstartsel, &newendsel);
03620             
03621             if (oldstartsel == newstartsel && oldendsel == newendsel && oldstartsel == oldendsel) {
03622             
03623                 wpsetcaretpos (forcemotionverb);
03624                 }
03625             }
03626         }
03627     
03628     if (keyboardstatus.keydirection != nodirection)
03629         pgSetCursorState (wpbuffer, toggle_cursor);
03630     
03631     wppostruleredit (undocode != undo_none, flvisi);
03632     
03633     return (true);
03634     } /*wpkeystroke*/
03635 
03636 
03637 boolean wpgo (tydirection dir, long dist) {
03638     
03639     /*
03640     simulate cursor motion in the indicated direction and distance.
03641     
03642     return true if any motion actually occurs.
03643     
03644     4.1b5 dmb: with WSE 2.2, WSKey can modify the event record. So we
03645     have to set it up each time through the loop
03646     
03647     4.1b6 dmb: test motion be comparing Pos and Carent fields of tBegin,
03648     not by seeing of pgGetSelection changes. Also, activate the text during
03649     move in case there's a selection. It won't update right if inacdtive.
03650     
03651     12/6/96 dmb: paige implementation
03652     
03653     5.1.5b7 dmb: handle ill-timed disposal of wpdata in wpactivate
03654     */
03655     
03656     boolean flmoved = false;
03657     boolean fldidnotmove = false;
03658     boolean flactive;
03659     pg_byte chkey = 0;
03660     long startsel, endsel;
03661     long newsel;
03662     
03663     if (!wppreedit ())
03664         return (false);
03665     
03666     wpresettyping ();
03667     
03668     flactive = wpisactive ();
03669     
03670     if (!flactive) {
03671         
03672         wpactivate (true);
03673         
03674         if (wpdata == nil)
03675             return (false);
03676         }
03677     
03678     wpgetselection (&startsel, &endsel);
03679     
03680     switch (dir) {
03681         
03682         case up: case flatup:
03683             chkey = chuparrow;
03684             
03685             break;
03686         
03687         case down: case flatdown:
03688             chkey = chdownarrow;
03689             
03690             break;
03691         
03692         case left:
03693             chkey = chleftarrow;
03694         //  wpsetselection (startsel - dist, startsel - dist);
03695             
03696             break;
03697         
03698         case right:
03699             chkey = chrightarrow;
03700         //  wpsetselection (endsel + dist, endsel + dist);
03701             
03702             break;
03703         
03704         default:
03705             break;
03706         }
03707     
03708     if (chkey != 0) {
03709         
03710         while (--dist >= 0) {
03711         
03712             pgInsert (wpbuffer, &chkey, sizeof (pg_byte), CURRENT_POSITION, key_insert_mode, 0, wpdisplay_way);
03713             
03714             wpgetselection (&newsel, &newsel);
03715             
03716             if ((newsel == startsel) && (newsel == endsel)) {
03717             
03718                 if (fldidnotmove)
03719                     break;
03720             
03721                 fldidnotmove = true;
03722                 }
03723             else {
03724                 startsel = endsel = newsel;
03725                 
03726                 fldidnotmove = false;
03727                 
03728                 flmoved = true;
03729                 }
03730             
03731             pgSetCursorState (wpbuffer, compute_cursor);
03732             }
03733         }
03734     
03735     if (!flactive) {
03736     
03737         wpactivate (false);
03738         
03739         if (wpdata == nil)
03740             return (false);
03741         }
03742     
03743     wppostedit (false);
03744     
03745     return (flmoved);
03746     } /*wpgo*/
03747 
03748 
03749 static boolean wprulerclick (Point pt) {
03750 #pragma unused (pt)
03751 
03752     boolean flrecalc = false;
03753     
03754 #if flrulers
03755     
03756     #endif
03757     
03758     return (flrecalc);
03759     } /*wprulerclick*/
03760 
03761 
03762 void wpclick (Point pt, tyclickflags flags) {
03763     
03764     register boolean flrecalc;
03765     Rect r;
03766     Point ptnew;
03767     co_ordinate point;
03768     boolean flinview;
03769     
03770     r = (**wpwindowinfo).contentrect;
03771     
03772     if (!pointinrect (pt, r))
03773         return;
03774     
03775     if (!wppreedit ()) 
03776         return;
03777     
03778     if ((**wpdata).flshowruler  && false /*pointinruler*/) {
03779         
03780         flrecalc = wprulerclick (pt);
03781         
03782         if (flrecalc) /*formatting was changed, update ruler right away*/
03783             shellsetselectioninfo ();
03784         }
03785     else {
03786         
03787         wpresettyping ();
03788         
03789         point.h = pt.h;
03790         point.v = pt.v;
03791         
03792         pgDragSelect (wpbuffer, &point, mouse_down, (short) flags, 0, FALSE);
03793         
03794         while (mousestilldown ()) {
03795         
03796             getmousepoint (&ptnew);
03797             
03798             point.h = ptnew.h;
03799             point.v = ptnew.v;
03800             
03801             flinview = pgPtInView (wpbuffer, &point, NULL) & WITHIN_VIS_AREA;
03802 
03803             if ((!flinview) || (ptnew.h != pt.h) || (ptnew.v != pt.v)) {
03804             
03805                 pgDragSelect (wpbuffer, &point, mouse_moved, (short) flags, 0, TRUE);
03806                 
03807                 pt = ptnew;
03808                 }
03809             
03810             CallTrackClickProc ((**wpdata).trackclickroutine, wpdata, pt);
03811             }
03812         
03813         pgDragSelect (wpbuffer, &point, mouse_up, (short) flags, 0, FALSE);
03814         
03815         flrecalc = false;
03816         }
03817     
03818     wppostruleredit (flrecalc, false);
03819     } /*wpclick*/
03820 
03821 
03822 static boolean wpinserttext (byte *ptext, long ctchars) {
03823     
03824     /*
03825     4.1b7 dmb: handle ctchars > maxint by giving it to WSE in short chunks
03826     
03827     5.0a9 dmb: fixed undo crashing bug
03828     
03829     5.0.2b17 dmb: added PG_TRY block
03830     
03831     5.0.2b18 dmb: always pgDelete to fix display bug
03832     */
03833     
03834     boolean fl = false;
03835     
03836     if (wppreedit ()) {
03837         
03838         pushundoaction (undopastestring);
03839         
03840         wpresettyping ();
03841         
03842         wppushundo (undo_insert, (void *) &ctchars);
03843         
03844         PG_TRY (&mem_globals)
03845         {
03846             //if (ctchars == 0)
03847                 pgDelete (wpbuffer, NULL, wpdisplay_way);
03848             
03849             //else
03850                 pgInsert (wpbuffer, (pg_byte_ptr) ptext, ctchars, CURRENT_POSITION, data_insert_mode, 0, wpdisplay_way);
03851             
03852             fl = true;
03853         }
03854         PG_CATCH
03855         {
03856             #ifdef MACVERSION
03857                 oserror (memFullErr);
03858             #endif
03859             #ifdef WIN95VERSION
03860                 oserror (ERROR_OUTOFMEMORY);
03861             #endif
03862         }
03863         PG_ENDTRY;
03864         
03865         (**wpdata).flstartedtyping = true;
03866         
03867         wppostruleredit (fl, fl);
03868         }
03869     
03870     return (fl);
03871     } /*wpinserttext*/
03872 
03873 
03874 boolean wpinserthandle (Handle htext) {
03875 
03876     /*
03877     PBS 7.0b22: Fixed display glitch by invalidating the rect before
03878     drawing. Now you don't get all the garbage characters when you
03879     choose a command that does a wp.insert.
03880     */
03881     
03882     boolean fl = false;
03883     boolean flhtmloutline = false;
03884     boolean fldisplaywasenabled = wpdisplayenabled ();
03885 
03886     if (wppreedit ()) {
03887 
03888         invalrect ((**wpdata).wprect); /*PBS 7.0b22*/
03889         
03890         wpresettyping ();
03891 
03892         if (outlinedata != NULL)
03893 
03894             if ((**outlinedata).flhtml)
03895 
03896                 flhtmloutline = true;
03897 
03898         if (flhtmloutline)
03899 
03900             wpsetdisplay (false);
03901         
03902         fl = wpinserttexthandle (wpbuffer, htext, wpdisplay_way, true);
03903 
03904         if (flhtmloutline) {
03905 
03906             long startsel, endsel;
03907 
03908             wpgetselection (&startsel, &endsel);
03909 
03910             opunloadeditbuffer ();
03911 
03912             oploadeditbuffer ();
03913 
03914             wpsetselection (startsel, endsel);
03915 
03916             if (fldisplaywasenabled)
03917 
03918                 wpsetdisplay (true);
03919             } /*if*/
03920         
03921         (**wpdata).flstartedtyping = true;
03922         
03923         wppostruleredit (fl, fl);
03924         }
03925     
03926     return (fl);
03927     } /*wpinserthandle*/
03928 
03929 
03930 boolean wpinsert (bigstring bs) {
03931     
03932     return (wpinserttext (bs + 1, stringlength (bs)));
03933     } /*wpinsert*/
03934 
03935 
03936 boolean wpdelete (boolean flinserting) {
03937 #pragma unused (flinserting)
03938 
03939     /*
03940     12/31/91 dmb: added flinserting parameter -- needed to deterinate whether 
03941     the undo of the deletion needs to redisplay or not
03942     */
03943     
03944     long startsel, endsel;
03945     
03946     pgGetSelection (wpbuffer, &startsel, &endsel);
03947     
03948     if (startsel == endsel)
03949         return (false);
03950     
03951     wppushundo (undo_delete, NULL);
03952     
03953     pgDelete (wpbuffer, NULL, wpdisplay_way);
03954     
03955     return (true);
03956     } /*wpdelete*/
03957 
03958 
03959 static void wpdisposescrap (void * hwp) {
03960     
03961     pgDispose ((pg_ref) hwp);
03962     } /*wpdisposescrap*/
03963 
03964 
03965 static boolean wpexportscrap (void *scrap, tyscraptype totype, Handle *htext, boolean *fltempscrap) {
03966 
03967     /*
03968     if the requested type isn't text, return false.  otherwise, try to 
03969     convert the given scrap to text
03970     */
03971     
03972     pg_ref hwp = (pg_ref) scrap;
03973     
03974     switch (totype) {
03975         
03976         case wpscraptype:
03977             if (!wppacktext (hwp, htext)) /*flat version for system scrap*/
03978                 return (false);
03979             
03980             break;
03981         
03982         case textscraptype: {
03983             select_pair range;
03984             text_ref text;
03985             
03986             range.begin = 0, range.end = pgTextSize (hwp);
03987             
03988             text = pgCopyText(hwp, &range, all_text_chars);
03989             
03990             if (text == MEM_NULL)
03991                 return (false);
03992 
03993             newfilledhandle (UseMemory (text), GetMemorySize (text), htext);
03994             
03995             UnuseAndDispose ((memory_ref) text);
03996             
03997             #ifdef xxxWIN95VERSION
03998                 if (htext != nil)
03999                     wpcr2crlf (*htext);
04000             #endif
04001 
04002             break;
04003             }
04004         
04005         case pictscraptype:
04006         //  SavePictToScrap ((pg_ref) data);
04007         
04008             return (false);
04009         
04010         default:
04011             return (false);
04012         }
04013     
04014     *fltempscrap = true;
04015             
04016     return (*htext != nil);
04017     } /*wpexportscrap*/
04018 
04019 
04020 static boolean wpsetscrap (pg_ref hwp) {
04021 
04022     return (shellsetscrap ((Handle) hwp, wpscraptype, &wpdisposescrap, &wpexportscrap));
04023     } /*wpsetscrap*/
04024 
04025 
04026 boolean wpscraphook (Handle hscrap) {
04027     
04028     /*
04029     if our private type is on the external clipboard, set the internal 
04030     scrap to it.
04031     */
04032     
04033     pg_ref pg;
04034     
04035     if (getscrap (wpscraptype, hscrap)) {
04036         
04037         if (wpunpacktext (hscrap, &pg))
04038             wpsetscrap (pg);
04039         
04040         return (false); /*don't call any more hooks*/
04041         }
04042     
04043     return (true); /*keep going*/
04044     } /*wpscraphook*/
04045 
04046 
04047 boolean wpcut (void) {
04048     
04049     if (!wppreedit ())
04050         return (false);
04051     
04052     pushundoaction (undocutstring);
04053     
04054     wppushundo (undo_delete, NULL);
04055     
04056     wpresettyping ();
04057     
04058     wpsetscrap (pgCut (wpbuffer, NULL, wpdisplay_way));
04059     
04060     wppostedit (true);
04061     
04062     return (true);
04063     } /*wpcut*/
04064 
04065 
04066 boolean wpcopy (void) {
04067 
04068     if (!wpsetglobals ())
04069         return (false);
04070     
04071     return (wpsetscrap (pgCopy (wpbuffer, NULL)));
04072     } /*wpcopy*/
04073 
04074 
04075 boolean wppaste (boolean flcanusestyle) {
04076 
04077     /*
04078     5.0b9 dmb: test display enabling for pg paste parameter
04079     */
04080 
04081     pg_ref hwpscrap;
04082     Handle htext;
04083     long len;
04084     boolean fltempscrap;
04085     
04086     if (!wppreedit ())
04087         return (false);
04088     
04089     pushundoaction (undopastestring);
04090     
04091     wpresettyping ();
04092     
04093     //  paste native paige if present
04094     
04095     if (flcanusestyle && shellconvertscrap (wpscraptype, (Handle *) &hwpscrap, &fltempscrap)) {
04096     
04097         wppushundo (undo_paste, (void *) hwpscrap);
04098         
04099         PG_TRY (&mem_globals) {
04100             
04101             pgPaste (wpbuffer, hwpscrap, CURRENT_POSITION, FALSE, wpdisplay_way);
04102             }
04103         PG_CATCH {
04104         
04105             memoryerror ();
04106             }
04107         PG_ENDTRY;
04108 
04109         if (fltempscrap)
04110             pgDispose (hwpscrap);
04111             
04112         }
04113     
04114     // no paige; try TEXT scrap
04115     
04116     else if (shellconvertscrap (textscraptype, &htext, &fltempscrap)) {
04117     
04118         lockhandle (htext);
04119         
04120         PG_TRY (&mem_globals) {
04121         
04122             len = gethandlesize (htext);
04123 
04124             wppushundo (undo_insert, (void *) &len);
04125             
04126             pgDelete (wpbuffer, NULL, wpdisplay_way); // 5.0d14 dmb: fixes display bug
04127             
04128             pgInsert (wpbuffer, (pg_byte_ptr) *htext, len, CURRENT_POSITION, data_insert_mode, 0, wpdisplay_way);
04129             }
04130         PG_CATCH {
04131         
04132             memoryerror ();
04133             }
04134         PG_ENDTRY;
04135         
04136         unlockhandle (htext);
04137         
04138         if (fltempscrap)
04139             disposehandle (htext);
04140         }
04141     
04142     // no paige or text, try PICT scrap
04143     
04144     else if (shellconvertscrap (pictscraptype, &htext, &fltempscrap)) {
04145         
04146         // *** paste pict
04147         if (fltempscrap)
04148             disposehandle (htext);
04149         }
04150     
04151     (**wpdata).flstartedtyping = true;
04152     
04153     wppostedit (true);
04154     
04155     return (true);
04156     } /*wppaste*/
04157 
04158 
04159 boolean wpclear (void) {
04160     
04161     boolean flrecalc;
04162     
04163     if (!wppreedit ())
04164         return (false);
04165     
04166     pushundoaction (undoclearstring);
04167     
04168     wpresettyping ();
04169     
04170     flrecalc = wpdelete (false);
04171     
04172     wppostedit (flrecalc);
04173     
04174     return (true);
04175     } /*wpclear*/
04176 
04177 
04178 boolean wpselectall (void) {
04179     
04180     return (wpsetselection (0L, longinfinity));
04181     } /*wpselectall*/
04182 
04183 
04184 boolean wpselectword (void) {
04185     
04186     long startsel, endsel;
04187     
04188     if (!wpsetglobals ())
04189         return (false);
04190     
04191     pgFindWord (wpbuffer, CURRENT_POSITION, &startsel, &endsel, TRUE, FALSE);
04192     
04193     return (wpsetselection (startsel, endsel));
04194     } /*wpselectword*/
04195 
04196 
04197 boolean wpselectline (void) {
04198     
04199     long startsel, endsel;
04200     Rect rbefore, rafter;
04201     
04202     if (!wpsetglobals ())
04203         return (false);
04204     
04205     if ((**wpdata).floneline)
04206         return (wpselectall());
04207     
04208     wpgetselrect (&rbefore);
04209     
04210     pgFindLine (wpbuffer, CURRENT_POSITION, &startsel, &endsel);
04211     
04212     wpsetselection (startsel, endsel);
04213     
04214     wpgetselrect (&rafter);
04215     
04216     if (rafter.top >= rbefore.bottom) { // wrong line
04217         
04218         pgFindLine (wpbuffer, startsel - 1, &startsel, &endsel);
04219         
04220         wpsetselection (startsel, endsel);
04221         }
04222     
04223     return (true);
04224     } /*wpselectline*/
04225 
04226 
04227 boolean wpselectpara (void) {
04228     
04229     long startsel, endsel;
04230     
04231     if (!wpsetglobals ())
04232         return (false);
04233     
04234     wpgetselection (&startsel, &endsel);
04235 
04236     pgFindPar (wpbuffer, endsel, &startsel, &endsel);
04237     
04238     return (wpsetselection (startsel, endsel));
04239     } /*wpselectpara*/
04240 
04241 
04242 boolean wpsetname (bigstring bsname) {
04243     
04244     /*
04245     allows an external caller to set the name of wpdata.
04246     */
04247     
04248     hdlstring hname;
04249     boolean fl;
04250     
04251     disposehandle ((Handle) (**wpdata).hname);
04252     
04253     fl = newheapstring (bsname, &hname);
04254     
04255     (**wpdata).hname = hname;
04256     
04257     wpdirty (true);
04258     
04259     return (fl);
04260     } /*wpsetname*/
04261 
04262 
04263 void wpresize (void) {
04264     
04265     Rect oldrect, newrect;
04266     co_ordinate grow;
04267     
04268     if (!wpsetglobals ()) 
04269         return;
04270     
04271     newrect = (**wpwindowinfo).contentrect;
04272     
04273     oldrect = (**wpwindowinfo).oldcontentrect;
04274     
04275     grow.h = newrect.right - oldrect.right;
04276     
04277     grow.v = newrect.bottom - oldrect.bottom;
04278     
04279     pgGrowVisArea (wpbuffer, NULL, &grow);
04280     
04281     (**wpdata).wprect.right += grow.h;
04282     
04283     (**wpdata).wprect.bottom += grow.v;
04284     
04285     wpresetscrollbars ();
04286     
04287     wpdirty (false);
04288     } /*wpresize*/
04289 
04290 
04291 boolean wptotalrecalc (void) {
04292     
04293     /*
04294     force a total recalc & redisplay
04295     */
04296     
04297     if (!wppreedit ())
04298         return (false);
04299     
04300     pgPaginateNow (wpbuffer, 0x7fffffff, FALSE);
04301     
04302     wppostedit (true);
04303     
04304     return (true);
04305     } /*wptotalrecalc*/
04306 
04307 
04308 boolean wpgetmaxpos (long *maxpos) {
04309 
04310     if (!wpsetglobals ())
04311         return (false);
04312     
04313     *maxpos = gettextlength (wpbuffer);
04314     
04315     return (true);
04316     } /*wpgetmaxpos*/
04317 
04318 
04319 boolean wpgetselection (long *startsel, long *endsel) {
04320 
04321     long newstartsel;
04322 
04323     if (!wpsetglobals ())
04324         return (false);
04325     
04326     pgGetSelection (wpbuffer, startsel, endsel);
04327 
04328     if (wptraversehiddentext (left, &newstartsel)) {
04329 
04330         wpsetselection (newstartsel, *endsel);
04331 
04332         pgGetSelection (wpbuffer, startsel, endsel);
04333         } /*if*/
04334     
04335     return (true);
04336     } /*wpgetselection*/
04337 
04338 
04339 boolean wpsetselection (long startsel, long endsel) {
04340 
04341     /*
04342     7/11/91 dmb: added call to resettyping
04343 
04344     12/5/96 dmb: paige
04345     
04346     5.0.2b18 dmb: call wpdirtyselectioninfo
04347     */
04348     
04349     boolean flactive;
04350     
04351     if (!wpsetglobals ())
04352         return (false);
04353     
04354     wppushdraw ();
04355     
04356     endsel = min (endsel, gettextlength (wpbuffer));
04357     
04358     startsel = min (startsel, endsel);
04359     
04360     wpresettyping ();
04361     
04362     flactive = wpisactive();
04363     
04364     if (!flactive)
04365         wpframeselection ();
04366     
04367     pgSetSelection (wpbuffer, startsel, endsel, 0, wpdisplayenabled () /*&& flactive*/);
04368     
04369     if (!flactive)
04370         wpframeselection ();
04371     
04372     wppopdraw ();
04373     
04374     wpdirtyselectioninfo ();
04375     
04376     wpupdate();  // 2006-05-04 smd: bug fix. background color will now be restored properly, so only the selected text looks selected
04377     
04378     return (true);
04379     } /*wpsetselection*/
04380 
04381 
04382 boolean wpundo (void) {
04383     
04384     undo_ref undo;
04385     
04386     if (!wppreedit ())
04387         return (false);
04388     
04389     undo = pgUndo (wpbuffer, getundo (), true, wpdisplay_way);
04390     
04391     wpdisposeundo (wpdata);
04392     
04393     setundo (undo);
04394     
04395     wppostedit (true);
04396     
04397     return (true);
04398     } /*wpundo*/
04399 
04400 
04401 boolean wpsearch (boolean flfromtop, boolean flcase, boolean flwords, boolean flwrap) {
04402 #pragma unused (flcase, flwords)
04403 
04404     /*
04405     9/12/91 dmb: supported flwrap parameter
04406     
04407     5.0a2 dmb: fixed loop bug in paige rewrite
04408     
04409     5.0.2b19 dmb: initialize flfound to false
04410     */
04411     
04412     paige_rec_ptr pg_rec;
04413     long ixstart, lenmatch;
04414     long startsel, endsel;
04415     long ixblock, ctblocks;
04416     text_block_ptr textblocks, block;
04417     boolean flfound = false;
04418     
04419     if (!wpsetglobals ())
04420         return (false);
04421     
04422     pgGetSelection (wpbuffer, &startsel, &endsel);
04423     
04424     if (flfromtop)
04425         ixstart = 0;
04426     else
04427         ixstart = endsel;
04428     
04429     pg_rec = (paige_rec_ptr) UseMemory (wpbuffer);
04430 
04431     textblocks = (text_block_ptr) UseMemory (pg_rec->t_blocks);
04432     
04433     ctblocks = GetMemorySize (pg_rec->t_blocks);
04434     
04435     for (ixblock = 0, block = textblocks; ixblock < ctblocks; ) {
04436     
04437         pg_byte_ptr ptext;
04438         long lentext;
04439         
04440         if (ixstart) {
04441         
04442             if (ixstart >= (*block).end)
04443                 goto nextblock; /*next buffer, please*/
04444             
04445             ixstart -= (*block).begin; /*convert to offset within buffer*/
04446             }
04447         
04448         lentext = GetMemorySize (block->text);
04449         
04450         ptext = (pg_byte_ptr) UseMemory (block->text);
04451         
04452         flfound = textsearch (ptext, lentext, &ixstart, &lenmatch);
04453         
04454         UnuseMemory (block->text);
04455         
04456         if (flfound)
04457             break;
04458         
04459         ixstart = 0; /*we've already searched the only partial buffer*/
04460         
04461         if (flwrap && (ixblock == ctblocks - 1)) { /*time to wrap*/
04462             
04463             ixblock = 0; /*restart from beginning*/
04464             
04465             block = textblocks;
04466             
04467             flwrap = false; /*only wrap once!*/
04468             
04469             continue; /*wrap around, don't increment block*/
04470             }
04471         
04472     nextblock:
04473     
04474         ++ixblock;
04475         
04476         ++block;
04477         }
04478     
04479     if (flfound) {
04480         
04481         boolean fldisplay = wpdisplayenabled () && wpisactive();
04482         long ixmatch;
04483         
04484         ixmatch = ixstart;
04485         
04486         ixmatch += (*block).begin;
04487         
04488         wpresettyping ();
04489         
04490         wpsetselection (ixmatch, ixmatch + lenmatch);
04491         
04492         if (fldisplay)
04493             wppushdraw ();
04494         
04495         wpvisicursor ();
04496         
04497         if (fldisplay)
04498             wppopdraw ();
04499         }
04500     
04501     UnuseMemory (pg_rec->t_blocks);
04502     
04503     UnuseMemory (wpbuffer);
04504     
04505     return (flfound);
04506     } /*wpsearch*/
04507 
04508 
04509 boolean wpadjustcursor (Point pt) {
04510     
04511     co_ordinate point;
04512     
04513     if (!wpsetglobals ())
04514         return (false);
04515     
04516     point.h = pt.h;
04517     point.v = pt.v;
04518     
04519     if (pgPtInView (wpbuffer, &point, NULL) & WITHIN_VIS_AREA)
04520         setcursortype (cursorisibeam);
04521     else
04522         setcursortype (cursorisarrow);
04523     
04524     return (true);
04525     } /*wpadjustcursor*/
04526 
04527 
04528 void wpidle (void) {
04529 
04530     /*
04531     7.0b16 PBS: On Windows, the caret can only be destroyed in the main thread.
04532     So wpactive, when asked to destroy the caret, sets fldestroycaret to true.
04533     Next time this routine is called from the main thread it destroys the caret.
04534     */
04535     
04536     if (wpsetglobals ()) {
04537         
04538         wppushdraw ();
04539         
04540         pgIdle (wpbuffer);
04541 
04542         #ifdef WIN95VERSION
04543 
04544         if (fldestroycaret) { /*7.0b16 PBS: on Windows, caret must be destroyed in main thread.*/
04545 
04546                 fldestroycaret = false; /*Reset*/
04547 
04548                 pgSetCursorState (wpbuffer, hide_cursor); /*Call Paige to destroy the caret*/
04549                 } /* if*/
04550         #endif
04551         
04552         wppopdraw ();
04553         }
04554     } /*wpidle*/
04555 
04556 
04557 #ifdef MACVERSION
04558 #pragma mark === formatting ===
04559 #endif
04560 
04561 
04562 boolean wpsetfont (void) {
04563     
04564     bigstring bsfont;
04565     
04566     if (!wppreedit ())
04567         return (false);
04568     
04569     pushundoaction (undoformatstring);
04570     
04571     wppushformatundo ();
04572     
04573     fontgetname ((**wpwindowinfo).selectioninfo.fontnum, bsfont);
04574     
04575     #ifdef WINDOWS_PLATFORM
04576         convertpstring (bsfont);
04577     #endif
04578     
04579     pgSetFontByName (wpbuffer, bsfont, NULL, wpdisplayenabled ());
04580     
04581     wppostedit (true);
04582     
04583     return (true);
04584     } /*wpsetfont*/
04585 
04586 
04587 boolean wpsetsize (void) {
04588     
04589     if (!wppreedit ())
04590         return (false);
04591     
04592     pushundoaction (undoformatstring);
04593     
04594     wppushformatundo ();
04595     
04596     pgSetPointSize (wpbuffer, (**wpwindowinfo).selectioninfo.fontsize, NULL, wpdisplayenabled ());
04597     
04598     wppostedit (true);
04599     
04600     return (true);
04601     } /*wpsetsize*/
04602 
04603 
04604 boolean wpsetstyle (void) {
04605     
04606     long    set_bits;
04607     long    style_bits = 0;
04608     
04609     if (!wppreedit ())
04610         return (false);
04611     
04612     pushundoaction (undoformatstring);
04613     
04614     wppushformatundo ();
04615     
04616     style_bits = (**wpwindowinfo).selectioninfo.fontstyle;
04617     
04618     if (style_bits == normal)
04619         set_bits = -1;
04620     else
04621         set_bits = style_bits;
04622     
04623     pgSetStyleBits (wpbuffer, style_bits, set_bits, NULL, wpdisplayenabled ());
04624     
04625     wppostedit (true);
04626     
04627     return (true);
04628     } /*wpsetstyle*/
04629 
04630 
04631 boolean wpsetleading (void) {
04632     
04633     par_info info;
04634     par_info mask;
04635     
04636     if (!wppreedit ())
04637         return (false);
04638     
04639     pgFillBlock(&info, sizeof(par_info), 0);
04640     pgInitParMask(&mask, 0);
04641     
04642     info.leading_extra = (long) (**wpwindowinfo).selectioninfo.leading;
04643     mask.leading_extra = -1;
04644     
04645     pushundoaction (undoformatstring);
04646     
04647     wppushrulerundo ();
04648     
04649     pgSetParInfo (wpbuffer, NULL, &info, &mask, wpdisplay_way);
04650     
04651     wppostruleredit (1, false);
04652     
04653     return (true);
04654     } /*wpsetleading*/
04655 
04656 
04657 boolean wpsetjustify (void) {
04658     
04659     par_info info;
04660     par_info mask;
04661     
04662     if (!wppreedit ())
04663         return (false);
04664     
04665     pgFillBlock (&info, sizeof (par_info), 0);
04666     
04667     pgInitParMask (&mask, 0);
04668     
04669     switch ((**wpwindowinfo).selectioninfo.justification) {
04670         
04671         case leftjustified:
04672             info.justification = justify_left;
04673             
04674             break;
04675             
04676         case centerjustified:
04677             info.justification = justify_center;
04678             
04679             break;
04680             
04681         case rightjustified:
04682             info.justification = justify_right;
04683             
04684             break;
04685             
04686         case fulljustified:
04687             info.justification = justify_full;
04688             
04689             break;
04690             
04691         default:
04692             return (false);
04693             
04694         } /*switch*/
04695     
04696     mask.justification = -1;
04697     
04698     pushundoaction (undoformatstring);
04699     
04700     wppushrulerundo ();
04701     
04702     pgSetParInfo (wpbuffer, NULL, &info, &mask, wpdisplay_way);
04703     
04704     wpdirtyselectioninfo ();
04705     
04706     wppostruleredit (1, false);
04707     
04708     return (true);
04709     } /*wpsetjustify*/
04710 
04711 
04712 boolean wpsetselectioninfo (void) {
04713     
04714     tyselectioninfo x;
04715     long selstyle, selstylemask;
04716     tyjustification j;
04717     bigstring bsfont;
04718     short size;
04719     par_info info;
04720     par_info mask;
04721     
04722     if (!wpsetglobals ())
04723         return (false);
04724     
04725     if (!wpownwindowinfo ())
04726         return (false);
04727     
04728     clearbytes (&x, sizeof (x)); /*initialize all fields to zero*/
04729     
04730     x.flcansetfont = true;
04731     
04732     x.flcansetsize = true;
04733     
04734     x.flcansetstyle = true;
04735     
04736     if (pgGetFontByName (wpbuffer, (pg_font_name_ptr) bsfont)) {
04737     
04738         #ifdef WINDOWS_PLATFORM
04739             convertcstring (bsfont);
04740         #endif
04741 
04742         fontgetnumber (bsfont, &x.fontnum);
04743         }
04744     else
04745         x.fontnum = -1; /*no consistent font across selection*/
04746     
04747     if (pgGetPointsize (wpbuffer, &size))
04748         x.fontsize = size;
04749     else
04750         x.fontsize = -1;
04751     
04752     pgGetStyleBits (wpbuffer, &selstyle, &selstylemask);
04753     
04754     x.fontstyle = selstyle & selstylemask;
04755     
04756     x.flcansetjust = true;
04757     
04758     x.flcansetleading = true;
04759     
04760     pgGetParInfo (wpbuffer, NULL, FALSE, &info, &mask);
04761     
04762     x.leading = info.leading_extra;
04763     
04764     switch (info.justification) {
04765     
04766         case justify_left:
04767             j = leftjustified;
04768             
04769             break;
04770             
04771         case justify_center:
04772             j = centerjustified;
04773             
04774             break;
04775             
04776         case justify_right:
04777             j = rightjustified;
04778             
04779             break;
04780             
04781         case justify_full:
04782             j = fulljustified;
04783             
04784             break;
04785         
04786         default:
04787             j = unknownjustification;
04788             
04789             break;
04790         }
04791     
04792     x.justification = j;
04793     
04794 //  if (wpgetruler ())
04795 //      wpdisplayruler (wpbuffer, TRUE);
04796     
04797     (**wpwindowinfo).selectioninfo = x;
04798     
04799     return (true);
04800     } /*wpsetselectioninfo*/
04801 
04802 
04803 static boolean wpsetverbindent (pg_indents *indents, pg_indents *mask) {
04804     
04805     if (!wppreedit ())
04806         return (false);
04807     
04808     pushundoaction (undoformatstring);
04809     
04810     wppushrulerundo ();
04811     
04812     pgSetIndents (wpbuffer, NULL, indents, mask, wpdisplay_way);
04813     
04814     wpdirtyselectioninfo (); /*force ruler update*/
04815     
04816     wppostruleredit (1, false);
04817     
04818     return (true);
04819     } /*wpsetverbindent*/
04820     
04821     
04822 boolean wpgetindent (short *indent) {
04823     
04824     pg_indents indents, mask;
04825     
04826     pgGetIndents (wpbuffer, NULL, &indents, &mask, NULL, NULL);
04827     
04828     *indent = indents.first_indent;
04829 
04830     return (true);
04831     } /*wpgetindent*/
04832 
04833 
04834 boolean wpsetindent (short indent) {
04835     
04836     pg_indents indents, mask = {0 ,0 ,-1};
04837     
04838     indents.first_indent = indent;
04839 
04840     return (wpsetverbindent (&indents, &mask));
04841     } /*wpsetindent*/
04842     
04843     
04844 boolean wpgetleftmargin (short *leftmargin) {
04845     
04846     pg_indents indents, mask;
04847     
04848     pgGetIndents (wpbuffer, NULL, &indents, &mask, NULL, NULL);
04849     
04850     *leftmargin = indents.left_indent;
04851 
04852     return (true);
04853     } /*wpgetleftmargin*/
04854 
04855 
04856 boolean wpsetleftmargin (short leftmargin) {
04857     
04858     pg_indents indents, mask = {-1, 0, 0};
04859     
04860     indents.left_indent = leftmargin;
04861 
04862     return (wpsetverbindent (&indents, &mask));
04863     } /*wpsetleftmargin*/
04864 
04865 
04866 boolean wpgetrightmargin (short *rightmargin) {
04867     
04868     pg_indents indents, mask;
04869     
04870     pgGetIndents (wpbuffer, NULL, &indents, &mask, NULL, NULL);
04871     
04872     *rightmargin = indents.right_indent;
04873 
04874     return (true);
04875     } /*wpgetrightmargin*/
04876 
04877 
04878 boolean wpsetrightmargin (short rightmargin) {
04879     
04880     pg_indents indents, mask = {0 ,-1 ,0};
04881     
04882     indents.right_indent = rightmargin;
04883     
04884     return (wpsetverbindent (&indents, &mask));
04885     } /*wpsetrightmargin*/
04886 
04887 
04888 boolean wpsettab (short pos, short tabjust, byte chfill) {
04889     
04890     /*
04891     9/27/91 dmb: set a tab at the indicated position.
04892     
04893     tabjust should be:
04894         0 - left
04895         1 - center
04896         2 - right
04897         3 - decimal
04898     
04899     chfill is the tab leader.  pass zero or space for no leader
04900     */
04901     
04902     tab_stop tab;
04903     
04904     if ((tabjust < 0) || (tabjust > 3))
04905         return (false);
04906     
04907     if (!wppreedit ())
04908         return (false);
04909     
04910     tab.tab_type = tabjust;
04911     
04912     tab.position = pos;
04913     
04914     if (chfill == chspace) /*if a space leader is specified, interpret as no leader*/
04915         chfill = chnul;
04916     
04917     tab.leader = chfill;
04918     
04919     pushundoaction (undoformatstring);
04920     
04921     wppushrulerundo ();
04922     
04923     pgSetTab (wpbuffer, NULL, &tab, wpdisplay_way);
04924     
04925     wpdirtyselectioninfo (); /*force ruler update*/
04926     
04927     wppostruleredit (1, false);
04928     
04929     return (true);
04930     } /*wpsettab*/
04931 
04932 
04933 boolean wpcleartabs (void) {
04934     
04935     /*
04936     9/27/91 dmb: remove all tabs for the current selection
04937     */
04938     
04939     long cttabs, ixtab;
04940     tab_ref tablist;
04941     tab_stop_ptr tab;
04942     long screen_offset;
04943     
04944     if (!wppreedit ())
04945         return (false);
04946     
04947     tablist = (tab_ref) MemoryAlloc (&mem_globals, sizeof (tab_stop), 0, 0);
04948     
04949     pgGetTabList (wpbuffer, NULL, tablist, MEM_NULL, &screen_offset);
04950     
04951     cttabs = GetMemorySize (tablist);
04952     
04953     if (cttabs > 0) {
04954         
04955         pushundoaction (undoformatstring);
04956         
04957         wppushrulerundo ();
04958         
04959         tab = (tab_stop_ptr) UseMemory (tablist);
04960         
04961         for (ixtab = 0; ixtab < cttabs; ++ixtab, ++tab) { /*traverse entire tab array*/
04962             
04963             (*tab).tab_type = no_tab;
04964             
04965             pgSetTab (wpbuffer, NULL, tab, wpdisplay_way);
04966             }
04967         
04968         wpdirtyselectioninfo (); /*force ruler update*/
04969         }
04970     
04971     wppostruleredit (1, false);
04972     
04973     return (cttabs > 0);
04974     } /*wpcleartabs*/
04975 
04976 

Generated on Wed May 31 18:20:04 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6