GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/****************************************************************************1**2*W gaptext.c XGAP source Frank Celler3**4**5*Y Copyright 1995-1997, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany6*Y Copyright 1997, Frank Celler, Huerth, Germany7**8** The GapTextWidget is intended to be used as a simple front end to the9** text widget with a gap text source and an ascii sink attached to it. It10** is a subclass of the standard text widget supplied with X11R4 and should11** work with X11R5 and X11R6.12*/13#include "utils.h"14#include "gaptext.h"1516extern void _XawTextPrepareToUpdate();17extern int _XawTextReplace();18extern void _XawTextSetScrollBars();19extern void _XawTextCheckResize();20extern void _XawTextExecuteUpdate();212223/****************************************************************************24**2526*F * * * * * * * * * * * * * * gap text widget * * * * * * * * * * * * * * *27*/282930/****************************************************************************31**3233*F GapTextInsertSelection( <w>, <evt>, <parms>, <nums> ) . . . . insert text34**35** DESCRIPTION36** Handle a selection insert event. 'GapTextInsertSelection' calls the37** input callback method with the selected string.38*/39#define CTR(a) ( a & 0x1f )4041static void GetSelection ( Widget, Time, String *, Cardinal );4243static void GapTextInsertSelection (44Widget w,45XEvent * evt,46String * parms,47Cardinal * nums )48{49Time time = 0;5051/* get the time of the event */52if ( evt != NULL )53switch ( evt->type )54{55case ButtonPress:56case ButtonRelease:57time = evt->xbutton.time;58break;59case KeyPress:60case KeyRelease:61time = evt->xkey.time;62break;63default:64time = CurrentTime;65break;66}6768/* and insert the selection */69GetSelection( w, time, parms, *nums );70}7172struct _SelectionList73{74String * params;75Cardinal count;76Time time;77};7879static void DoSelection (80Widget w,81XtPointer cd,82Atom * selection,83Atom * type,84XtPointer value,85UInt * length,86Int * format )87{88GapTextWidget gap = (GapTextWidget) w;89char buf[2];90String ptr;91Boolean nl;92Int len;9394if ( *type == 0 || *length == 0 )95{96struct _SelectionList* list = (struct _SelectionList*)cd;9798if ( list != NULL )99{100GetSelection( w, list->time, list->params, list->count );101XtFree(cd);102}103return;104}105106/* check if string begins with gap prompt */107ptr = (char*) value;108len = *length;109if ( gap->gap.drop_gap_prompt )110{111if ( 2 < len && ptr[0] == '>' && ptr[1] == ' ' )112{113ptr += 2;114len -= 2;115}116else if ( 5 < len && !strncmp( ptr, "gap> ", 5 ) )117{118ptr += 5;119len -= 5;120}121else if ( 5 < len && !strncmp( ptr, "brk> ", 5 ) )122{123ptr += 5;124len -= 5;125}126}127128/* and call the callback */129buf[0] = '@';130for ( nl = False; 0 < len; len--, ptr++ )131{132if ( nl && gap->gap.drop_gap_prompt )133{134if ( 2 < len && ptr[0] == '>' && ptr[1] == ' ' )135{136ptr += 1;137len -= 1;138continue;139}140else if ( 5 < len && !strncmp( ptr, "gap> ", 5 ) )141{142ptr += 4;143len -= 4;144continue;145}146else if ( 5 < len && !strncmp( ptr, "brk> ", 5 ) )147{148ptr += 4;149len -= 4;150}151}152if ( CTR('@') < *ptr && *ptr <= CTR('Z') )153{154buf[1] = '@' + *ptr;155gap->gap.input_callback( buf, 2 );156}157else if ( *ptr == '@' )158{159buf[1] = '@';160gap->gap.input_callback( buf, 2 );161}162else163gap->gap.input_callback( ptr, 1 );164nl = *ptr == '\n' || *ptr == '\r';165}166XtFree(cd);167XFree(value);168}169170static void GetSelection (171Widget w,172Time time,173String * parms,174Cardinal nums )175{176Atom selection;177Int buffer;178179/* try to find which buffer <*parms> is pointing to */180selection = XInternAtom( XtDisplay(w), *parms, False );181switch (selection)182{183case XA_CUT_BUFFER0: buffer = 0; break;184case XA_CUT_BUFFER1: buffer = 1; break;185case XA_CUT_BUFFER2: buffer = 2; break;186case XA_CUT_BUFFER3: buffer = 3; break;187case XA_CUT_BUFFER4: buffer = 4; break;188case XA_CUT_BUFFER5: buffer = 5; break;189case XA_CUT_BUFFER6: buffer = 6; break;190case XA_CUT_BUFFER7: buffer = 7; break;191default: buffer = -1; break;192}193194/* if <*parms> is a cut buffer insert its contents */195if ( buffer >= 0 )196{197Atom type = XA_STRING;198Int fmt8 = 8;199Int nbytes;200String line;201UInt length;202203line = XFetchBuffer( XtDisplay(w), &nbytes, buffer );204if ( 0 < ( length = nbytes ) )205DoSelection( w, NULL, &selection, &type, (caddr_t) line,206&length, &fmt8 );207else if ( 1 < nums )208GetSelection( w, time, parms+1, nums-1 );209}210else211{212struct _SelectionList * list;213214if ( --nums )215{216list = XtNew(struct _SelectionList);217list->params = parms + 1;218list->count = nums;219list->time = time;220}221else222list = NULL;223XtGetSelectionValue( w, selection, XA_STRING,224(XtSelectionCallbackProc) DoSelection, (XtPointer)list, time );225}226}227228229/****************************************************************************230**231*F GapTextInsertChar( <w>, <evt>, <parms>, <nums> ) . . . . . . handle keys232**233** DESCRIPTION234** Handle a key event. 'GapTextInsertChar' calls the input callback method235** with a one (or possible more) character string.236*/237static void GapTextInsertChar (238Widget w,239XEvent * evt,240String * parms,241Cardinal * nums )242{243GapTextWidget gap = (GapTextWidget) w;244Int len;245KeySym keysym;246String ptr;247char buf[2];248char str[128];249250/* if no input call is registered return */251if ( gap->gap.input_callback == 0 )252return;253254/* convert key event into text string */255len = XLookupString( &(evt->xkey), str, 128, &keysym, 0 );256257/* handle arrows keys, etc */258if ( len == 0 )259{260len = 1;261str[len] = 0;262/* Switched Arrow Up and PageUp behaviour, and263Arrow Down and PageDown behaviour resp., 22.3.1999 Max */264if ( keysym == XK_Left )265str[0] = CTR('B');266else if ( keysym == XK_Up )267str[0] = CTR('P');268else if ( keysym == XK_Right )269str[0] = CTR('F');270else if ( keysym == XK_Down )271str[0] = CTR('N');272else if ( keysym == XK_Prior )273{274len = 2;275strcpy( str, "\001\020" );276}277else if ( keysym == XK_Next )278{279len = 2;280strcpy( str, "\001\016" );281}282else if ( keysym == XK_Home )283{284len = 2;285strcpy( str, "\033<" );286}287else if ( keysym == XK_Insert )288str[0] = CTR('L');289else290return;291}292293/* and call the callback */294buf[0] = '@';295for ( ptr = str; 0 < len; len--, ptr++ )296{297if ( CTR('@') < *ptr && *ptr <= CTR('Z') )298{299buf[1] = '@' + *ptr;300gap->gap.input_callback( buf, 2 );301}302else if ( *str == '@' )303{304buf[1] = '@';305gap->gap.input_callback( buf, 2 );306}307else308gap->gap.input_callback( ptr, 1 );309}310return;311}312313314/****************************************************************************315**316*F GapTextSelectStart( <w>, <evt>, <parms>, <nums> ) . . . . pointer select317*/318static void GapTextSelectStart (319Widget w,320XEvent * evt,321String * parms,322Cardinal * nums )323{324GapTextWidget gap = (GapTextWidget) w;325TextWidget ctx = (TextWidget) w;326XawTextPosition oldPos;327XawTextPosition newPos;328329/* save text position */330oldPos = gap->text.insertPos;331332/* hide cursor, it will be make visible again in 'GapTextExtendEnd' */333XawTextDisplayCaret( w, False );334335/* call our superclass */336XtCallActionProc( w, "select-start", evt, parms, *nums );337338/* and restore text position */339if ( gap->gap.check_caret_pos != 0 )340newPos = oldPos+gap->gap.check_caret_pos(gap->text.insertPos,oldPos);341else342newPos = oldPos;343if ( newPos == oldPos )344ctx->text.insertPos = oldPos;345else346XawTextSetInsertionPoint( w, newPos );347}348349350/****************************************************************************351**352*F GapTextExtendAdjust( <w>, <evt>, <parms>, <nums> ) . . . pointer adjust353*/354static void GapTextExtendAdjust (355Widget w,356XEvent * evt,357String * parms,358Cardinal * nums )359{360GapTextWidget gap = (GapTextWidget) w;361TextWidget ctx = (TextWidget) w;362XawTextPosition oldPos;363364/* save text position */365oldPos = gap->text.insertPos;366367/* call our superclass */368XtCallActionProc( w, "extend-adjust", evt, parms, *nums );369370/* and restore text position */371ctx->text.insertPos = oldPos;372373/* XawTextSetInsertionPoint( w, oldPos ); */374}375376377/****************************************************************************378**379*F GapTextExtendEnd( <w>, <evt>, <parms>, <nums> ) . . . pointer select end380*/381static void GapTextExtendEnd (382Widget w,383XEvent * evt,384String * parms,385Cardinal * nums )386{387GapTextWidget gap = (GapTextWidget) w;388TextWidget ctx = (TextWidget) w;389XawTextPosition oldPos;390391/* save text position */392oldPos = gap->text.insertPos;393394/* call our superclass */395XtCallActionProc( w, "extend-end", evt, parms, *nums );396397/* and restore text position */398ctx->text.insertPos = oldPos;399400/* show cursor again, it is hidden in 'GapTextSelectStart' */401XawTextDisplayCaret( w, True );402403/* XawTextSetInsertionPoint( w, oldPos ); */404}405406407/****************************************************************************408**409*F GapTextInitialize( <req>, <new>, <args>, <nums> ) . . . . make new widget410*/411static void GapTextInitialize (412Widget request,413Widget new,414ArgList args,415Cardinal * nums )416{417GapTextWidget w = (GapTextWidget) new;418Int i;419Int tabs[64];420Int tab;421422/* initialize gap source and ascii sink */423if ( request->core.height == DEFAULT_TEXT_HEIGHT )424new->core.height = DEFAULT_TEXT_HEIGHT;425w->text.source = XtCreateWidget( "textSource",426gapSrcObjectClass,427new,428args, *nums );429w->text.sink = XtCreateWidget( "textSink",430asciiSinkObjectClass,431new,432args, *nums );433434if ( w->core.height == DEFAULT_TEXT_HEIGHT )435w->core.height = VMargins(w)+XawTextSinkMaxHeight(w->text.sink,1);436w->gap.drop_gap_prompt = False;437438/* set tab stops */439for ( i = 0, tab = 0; i < 64; i++)440tabs[i] = (tab += 8);441XawTextSinkSetTabs( w->text.sink, 64, tabs );442443/* enable redisplay in text object */444XawTextDisableRedisplay(new);445XawTextEnableRedisplay(new);446}447448449/****************************************************************************450**451*F GapTextDestroy( <w> ) . . . . . . . . . . . . destroy a gap text widget452*/453static void GapTextDestroy (454Widget w )455{456GapTextWidget gap = (GapTextWidget) w;457458if ( w == XtParent(gap->text.source) )459XtDestroyWidget( gap->text.source );460461if ( w == XtParent(gap->text.sink) )462XtDestroyWidget( gap->text.sink );463}464465466/****************************************************************************467**468469*V GapTextResources . . . . . . . . . . . . . . . . . resources of gap text470*/471#define offset(field) XtOffset(GapTextWidget, gap.field)472473static XtResource GapTextResources[] =474{475/* gap text resources */476{ XtNinputCallback, XtCInputCallback, XtRPointer,477sizeof(char*), offset(input_callback), XtRPointer,4780479},480{ XtNcheckCaretPos, XtCCheckCaretPos, XtRPointer,481sizeof(char*), offset(check_caret_pos), XtRPointer,4820483},484485/* other resources */486{ XtNtinyFont, XtCTinyFont, XtRFontStruct,487sizeof(XFontStruct*), offset(tiny_font), XtRString,488"-*-*-*-r-*-*-8-*-*-*-*-*-*-1"489},490{ XtNsmallFont, XtCSmallFont, XtRFontStruct,491sizeof(XFontStruct*), offset(small_font), XtRString,492"-*-*-*-r-*-*-10-*-*-*-*-*-*-1"493},494{ XtNnormalFont, XtCNormalFont, XtRFontStruct,495sizeof(XFontStruct*), offset(normal_font), XtRString,496"-*-*-*-r-*-*-13-*-*-*-*-*-*-1"497},498{ XtNlargeFont, XtCLargeFont, XtRFontStruct,499sizeof(XFontStruct*), offset(large_font), XtRString,500"-*-*-*-r-*-*-15-*-*-*-*-*-*-1"501},502{ XtNhugeFont, XtCHugeFont, XtRFontStruct,503sizeof(XFontStruct*), offset(huge_font), XtRString,504"-*-*-*-r-*-*-20-*-*-*-*-*-*-1"505},506{ XtNtitlePosition, XtCTitlePosition, XtRString,507sizeof(String), offset(title_position), XtRString,508"middle"509},510{ XtNpasteGapPrompt, XtCPasteGapPrompt, XtRBoolean,511sizeof(Boolean), offset(paste_gap_prompt), XtRString,512"False"513},514{ XtNquitGapCtrD, XtCQuitGapCtrD, XtRBoolean,515sizeof(Boolean), offset(quit_gap_ctrd), XtRString,516"False"517},518{ XtNcolorModel, XtCColorModel, XtRString,519sizeof(String), offset(color_model), XtRString,520"default"521},522{ XtNcolors, XtCColors, XtRString,523sizeof(String), offset(colors), XtRString,524"default"525}526};527528#undef offset529530531/****************************************************************************532**533*V GapTextActions . . . . . . . . . . . . . . . . . . actions for gap text534*/535static XtActionsRec GapTextActions[] =536{537{ "gap-insert-char", GapTextInsertChar },538{ "gap-insert-selection", GapTextInsertSelection },539{ "gap-select-start", GapTextSelectStart },540{ "gap-extend-adjust", GapTextExtendAdjust },541{ "gap-extend-end", GapTextExtendEnd }542};543544545/****************************************************************************546**547*V GapTextTranslations . . . . . . . . . . . . . . . . . action translations548*/549static char GapTextTranslations[] =550"\551<Key>: gap-insert-char()\n\552<Btn1Down>: gap-select-start()\n\553<Btn1Motion>: gap-extend-adjust()\n\554<Btn1Up>: gap-extend-end( PRIMARY, CUT_BUFFER0 )\n\555<Btn2Down>: gap-insert-selection( PRIMARY, CUT_BUFFER0 )\n\556";557558559/****************************************************************************560**561*V gapTextWidgetClass . . . . . . . . . . . . . . . . gap text class record562*/563GapTextClassRec gapTextClassRec =564{565{ /* Core fields */566/* superclass */ (WidgetClass) &textClassRec,567/* class_name */ "GapText",568/* widget_size */ sizeof(GapRec),569/* class_initialize */ XawInitializeWidgetSet,570/* class_part_init */ NULL,571/* class_inited */ FALSE,572/* initialize */ GapTextInitialize,573/* initialize_hook */ NULL,574/* realize */ XtInheritRealize,575/* actions */ GapTextActions,576/* num_actions */ XtNumber(GapTextActions),577/* resources */ GapTextResources,578/* num_resource */ XtNumber(GapTextResources),579/* xrm_class */ NULLQUARK,580/* compress_motion */ TRUE,581#if HAVE_BROKEN_TEXT_EXPORE_COMPRESS582/* compress_exposure */ XtExposeNoCompress,583#else584/* compress_exposure */ XtExposeGraphicsExpose | XtExposeNoExpose,585#endif586/* compress_enterleave*/ TRUE,587/* visible_interest */ FALSE,588/* destroy */ GapTextDestroy,589/* resize */ XtInheritResize,590/* expose */ XtInheritExpose,591/* set_values */ NULL,592/* set_values_hook */ NULL,593/* set_values_almost */ XtInheritSetValuesAlmost,594/* get_values_hook */ NULL,595/* accept_focus */ XtInheritAcceptFocus,596/* version */ XtVersion,597/* callback_private */ NULL,598/* tm_table */ GapTextTranslations,599/* query_geometry */ XtInheritQueryGeometry600},601{ /* Simple fields */602/* change_sensitive */ XtInheritChangeSensitive603},604{ /* Text fields */605/* empty */ 0606},607{ /* Gap fields */608/* empty */ 0609}610};611612WidgetClass gapTextWidgetClass = (WidgetClass)&gapTextClassRec;613614615/****************************************************************************616**617618*F * * * * * * * * * * * * gap text source widget * * * * * * * * * * * * *619*/620621622/****************************************************************************623**624625*F GapSrcInitialize( <req>, <new>, <args>, <nums> ) . . . . .new gap source626*/627static void GapSrcInitialize (628Widget request,629Widget new,630ArgList args,631Cardinal * nums )632{633GapSrcObject src = (GapSrcObject) new;634635/* initially we use a 16KByte output buffer */636src->gap_src.size = 16 * 1024;637src->gap_src.buffer = XtMalloc(src->gap_src.size);638src->gap_src.length = 0;639}640641642/****************************************************************************643**644*F GapSrcDestroy( <w> ) . . . . . . . . . . . . destroy a gap source object645*/646static void GapSrcDestroy (647Widget w )648{649GapSrcObject src = (GapSrcObject) w;650651/* free the output buffer */652XtFree( src->gap_src.buffer );653}654655656/****************************************************************************657**658*F GapSrcReadText( <w>, <pos>, <text>, <len> ) . . . get a piece of our text659**660** DESCRIPTION661** 'GapSrcReadText' sets the pointer <text>.ptr to the text of <w>662** starting at position <pos> and length <len>.663**664** RETURNS665** 'GapSrcReadText' returns the position relative to the beginning of text666** of <w> of the last character in <text>.667*/668static XawTextPosition GapSrcReadText (669Widget w,670XawTextPosition pos,671XawTextBlock * text,672unsigned long length )673{674GapSrcObject src = (GapSrcObject) w;675676text->firstPos = pos;677text->ptr = src->gap_src.buffer + pos;678text->length = src->gap_src.length - pos;679text->format = FMT8BIT;680if ( length < text->length )681text->length = length;682return pos + text->length;683}684685686/****************************************************************************687**688*F GapSrcReplaceText( <w>, <start>, <end>, <text> ) . replace a text piece689**690** DESCRIPTION691** Replace the text of <w> starting with <start> and ending before <end>692** with the text given in <text>.693**694** RETURNS695** Either 'XawEditDone' or 'XawPositionError'.696*/697static int GapSrcReplaceText (698Widget w,699XawTextPosition start,700XawTextPosition end,701XawTextBlock * text )702{703GapSrcObject src = (GapSrcObject) w;704String p;705String q;706String e;707708/* remove text from <start> to end */709p = src->gap_src.buffer + start;710q = src->gap_src.buffer + end;711e = src->gap_src.buffer + src->gap_src.length;712while ( p < e )713*p++ = *q++;714src->gap_src.length += start - end;715716/* now insert the new text */717if ( 0 < text->length )718{719if ( src->gap_src.size < src->gap_src.length + text->length )720{721src->gap_src.size += 16*1024 + text->length;722src->gap_src.buffer = XtRealloc( src->gap_src.buffer,723src->gap_src.size );724}725p = ( src->gap_src.buffer + src->gap_src.length ) - 1;726q = p + text->length;727e = src->gap_src.buffer + start;728while ( e <= p )729*q-- = *p--;730q = text->ptr;731p = e;732e = p + text->length;733while ( p < e )734*p++ = *q++;735src->gap_src.length += text->length;736}737return XawEditDone;738}739740741/****************************************************************************742**743*F GapSrcScan( <w>, <pos>, <type>, <dir>, <cnt>, <inc> ) . . . . . scan text744**745** DESCRIPTION746** Scan the text in <w>.buffer for the <cnt>.th occurance of a boundary of747** type <type>. Start the scan at position <pos>. If <include> is true748** include the boundary in the returned position.749**750** RETURNS751** 'Scan' returns the position of the boundary.752*/753static XawTextPosition GapSrcScan (754Widget w,755XawTextPosition pos,756XawTextScanType type,757XawTextScanDirection dir,758int cnt,759int ind )760{761GapSrcObject src = (GapSrcObject) w;762Int inc;763String p;764765/* first or last position in our text */766if ( type == XawstAll )767return (dir == XawsdRight) ? src->gap_src.length : 0;768769/* set <pos> to a sensible value */770if ( pos > src->gap_src.length )771pos = src->gap_src.length;772773/* we cannot scan left of position 0 or right of the text end */774if ( dir == XawsdRight && pos == src->gap_src.length )775return src->gap_src.length;776else if ( dir == XawsdLeft && pos == 0 )777return 0;778else if ( dir == XawsdLeft )779pos--;780781/* <inc> is used to increment (decrement) <p> and <pos> */782inc = (dir == XawsdRight) ? 1 : -1;783784/* handle different types of boundaries <cnt> times */785switch ( type )786{787case XawstAll: /* is not possible */788return (dir == XawsdRight) ? src->gap_src.length : 0;789break;790791case XawstEOL:792case XawstParagraph:793if ( dir == XawsdRight )794{795for ( ; 0 < cnt; cnt-- )796{797p = src->gap_src.buffer + pos;798while ( pos < src->gap_src.length )799{800if ( *p == '\n' )801break;802pos++; p++;803}804if ( src->gap_src.length < pos )805return src->gap_src.length;806pos++;807}808}809else810{811for ( ; 0 < cnt; cnt-- )812{813p = src->gap_src.buffer + pos;814while ( 0 <= pos )815{816if ( *p == '\n' )817break;818pos--; p--;819}820if ( pos < 0 )821return 0;822pos--;823}824}825if ( !ind )826pos -= inc;827break;828829830case XawstWhiteSpace:831for ( ; 0 < cnt; cnt-- )832{833Boolean nonSpace = FALSE;834835p = src->gap_src.buffer + pos;836while ( 0 <= pos && pos < src->gap_src.length )837{838if ( *p == ' ' || *p == '\t' || *p == '\n' )839{840if ( nonSpace )841break;842}843else844nonSpace = TRUE;845pos += inc;846p += inc;847}848if ( pos < 0 )849return 0;850if ( src->gap_src.length < pos )851return src->gap_src.length;852pos += inc;853}854if ( !ind )855pos -= inc;856break;857858case XawstPositions:859pos += cnt * inc;860break;861862default:863break;864}865if ( dir == XawsdLeft )866pos++;867868/* set <pos> to a sensible value and return */869if ( pos >= src->gap_src.length )870return src->gap_src.length;871else if ( pos < 0 )872return 0;873else874return pos;875}876877878/****************************************************************************879**880*V gapSrcObjectClass . . . . . . . . . . . . . . . . gap source class record881*/882GapSrcClassRec gapSrcClassRec =883{884{ /* core_class fields */885/* superclass */ (WidgetClass) (&textSrcClassRec),886/* class_name */ "GapSrc",887/* widget_size */ sizeof(GapSrcRec),888/* class_initialize */ XawInitializeWidgetSet,889/* class_part_initialize */ NULL,890/* class_inited */ FALSE,891/* initialize */ (XtInitProc) GapSrcInitialize,892/* initialize_hook */ NULL,893/* realize */ NULL,894/* actions */ NULL,895/* num_actions */ 0,896/* resources */ NULL,897/* num_resources */ 0,898/* xrm_class */ NULLQUARK,899/* compress_motion */ FALSE,900/* compress_exposure */ FALSE,901/* compress_enterleave */ FALSE,902/* visible_interest */ FALSE,903/* destroy */ GapSrcDestroy,904/* resize */ NULL,905/* expose */ NULL,906/* set_values */ NULL,907/* set_values_hook */ NULL,908/* set_values_almost */ NULL,909/* get_values_hook */ NULL,910/* accept_focus */ NULL,911/* version */ XtVersion,912/* callback_private */ NULL,913/* tm_table */ NULL,914/* query_geometry */ NULL,915/* display_accelerator */ NULL,916/* extension */ NULL917},918{ /* textSrc_class fields */919/* Read */ (XawTextPosition (*)())GapSrcReadText,920/* Replace */ (int (*)()) GapSrcReplaceText,921/* Scan */ (XawTextPosition (*)()) GapSrcScan,922/* Search */ XtInheritSearch,923/* SetSelection */ XtInheritSetSelection,924/* ConvertSelection */ XtInheritConvertSelection925},926{ /* GapSrc_class fields */927/* Keep the compiler happy */ NULL928}929};930931WidgetClass gapSrcObjectClass = (WidgetClass)&gapSrcClassRec;932933934/* * * * * * * * * * * * * gap text widget functions * * * * * * * * * * * */935936937/****************************************************************************938**939940*F CheckTextBlock( <block> ) . . . . . . . . check a block for special chars941*/942#if 0943static char * CheckTextBlockTmp = 0;944945static void CheckTextBlock ( XawTextBlock * block )946{947unsigned char * p;948unsigned char * q;949unsigned int i;950unsigned int s;951952p = (unsigned char*) block->ptr;953for ( s = 0, i = 0; i < block->length; i++, p++ )954if ( *p < 32 && *p != '\n' && *p != '\r' )955s++;956if ( s == 0 )957return;958if ( CheckTextBlockTmp != 0 )959XtFree(CheckTextBlockTmp);960CheckTextBlockTmp = XtMalloc(block->length + s);961p = (unsigned char*) block->ptr;962q = (unsigned char*) CheckTextBlockTmp;963for ( i = 0; i < block->length; i++, p++ )964{965if ( *p < 32 )966{967*q++ = '^';968*q++ = *p + 'A';969}970else971*q++ = *p;972}973block->ptr = CheckTextBlockTmp;974}975#endif976977978/****************************************************************************979**980*F GTPosition( <w> ) . . . . . . . . . . . . . . . . return insertion point981*/982Int GTPosition ( Widget w )983{984GapTextWidget gap = (GapTextWidget) w;985986return gap->text.insertPos;987}988989990/****************************************************************************991**992*F GTSetPosition( <w>, <pos> ) . . . . . . . . . . . . set insertion point993*/994void GTSetPosition ( Widget w, Int pos )995{996XawTextSetInsertionPoint( w, pos );997}9989991000/****************************************************************************1001**1002*F GTDelete( <w>, <dir>, <type> ) . . . . . . . . . delete a piece of text1003*/1004void GTDelete ( Widget w, XawTextScanDirection dir, XawTextScanType type )1005{1006GapTextWidget gap = (GapTextWidget) w;1007XawTextBlock text;1008Int to;1009Int from;10101011/* prepare text for update */1012_XawTextPrepareToUpdate(gap);1013gap->text.time = CurrentTime;10141015/* find <to> and <from> */1016to = GapSrcScan(gap->text.source,gap->text.insertPos,type,dir,1,TRUE);10171018if ( to == gap->text.insertPos )1019to = GapSrcScan(gap->text.source,gap->text.insertPos,type,dir,2,TRUE);1020if (dir == XawsdLeft)1021{1022from = to;1023to = gap->text.insertPos;1024}1025else1026from = gap->text.insertPos;10271028/* remove text */1029text.length = 0;1030text.firstPos = 0;1031if ( _XawTextReplace( gap, from, to, &text ) )1032{1033XBell(XtDisplay(gap), 50);1034goto error;1035}1036gap->text.insertPos = from;1037gap->text.showposition = TRUE;1038_XawTextSetScrollBars(gap);10391040/* do update */1041error:1042_XawTextCheckResize(gap);1043_XawTextExecuteUpdate(gap);1044gap->text.mult = 1;1045}104610471048/****************************************************************************1049**1050*F GTInsertText( <w>, <str>, <len> ) . . . . . insert <str> into a gap text1051**1052** DESCRIPTION1053** This functions insert the text pointed to by <str> of length <len> in1054** the gap text widget at the current position. It is the responsibility1055** of the caller to set the current insertion position.1056*/1057void GTInsertText ( Widget w, String str, Int len )1058{1059GapTextWidget gap = (GapTextWidget) w;1060XawTextBlock block;10611062/* convert text into a text block */1063block.firstPos = 0;1064block.ptr = (char*) str;1065block.format = FMT8BIT;1066block.length = len;1067#if 01068CheckTextBlock(&block);1069#endif10701071/* insert text at current position */1072XawTextReplace( w, gap->text.insertPos, gap->text.insertPos, &block );10731074/* move insertion position */1075XawTextSetInsertionPoint( w, gap->text.insertPos+len );1076}107710781079/****************************************************************************1080**1081*F GTReplaceText( <w>, <str>, <len> ) . . . . . replace last line by <str>1082**1083** DESCRIPTION1084** This functions replaces the text right of the insert point by the text1085** pointed to by <str> of length <len>. It is the responsibility of the1086** caller to set the current insertion position.1087*/1088void GTReplaceText ( Widget w, String str, Int len )1089{1090GapTextWidget gap = (GapTextWidget) w;1091XawTextBlock block;10921093/* convert text into a text block */1094block.firstPos = 0;1095block.ptr = (char*) str;1096block.format = FMT8BIT;1097block.length = len;1098#if 01099CheckTextBlock(&block);1100#endif11011102/* insert text at current position */1103XawTextReplace(w,gap->text.insertPos,gap->text.insertPos+len,&block);11041105/* move insertion position */1106XawTextSetInsertionPoint( w, gap->text.insertPos+len );1107}110811091110/****************************************************************************1111**1112*F GTMoveCaret( <w>, <rpos> ) . . . move caret relative to current position1113*/1114void GTMoveCaret ( Widget w, Int rpos )1115{1116GapTextWidget gap = (GapTextWidget) w;1117Int pos;11181119pos = gap->text.insertPos+rpos;1120if ( pos < 0 )1121pos = 0;1122if ( ((GapSrcObject)gap->text.source)->gap_src.length < pos )1123pos = ((GapSrcObject)gap->text.source)->gap_src.length;1124XawTextSetInsertionPoint( w, pos );1125}112611271128/****************************************************************************1129**1130*F GTDeleteLeft( <w> ) . . . . . . . . . . . delete a char left of the caret1131*/1132void GTDeleteLeft ( Widget w )1133{1134GapTextWidget gap = (GapTextWidget) w;11351136/* check if there is a character to the left */1137if ( gap->text.insertPos <= 0 )1138return;11391140/* use 'GTDelete' */1141GTDelete( w, XawsdLeft, XawstPositions );1142}114311441145/****************************************************************************1146**1147*F GTDeleteRight( <w> ) . . . . . . . . . delete a char right of the caret1148*/1149void GTDeleteRight ( Widget w )1150{1151GapTextWidget gap = (GapTextWidget) w;11521153/* check if there is a character to the right */1154if ( ((GapSrcObject)gap->text.source)->gap_src.length1155<=1156gap->text.insertPos )1157return;11581159/* use 'GTDelete' */1160GTDelete( w, XawsdRight, XawstPositions );1161}116211631164/****************************************************************************1165**1166*F GTBell( <w> ) . . . . . . . . . . . . . . . . . . . . . . . ring my bell1167*/1168void GTBell ( Widget w )1169{1170XBell( XtDisplay(w), 50 );1171}117211731174/****************************************************************************1175**1176*F GTDropGapPrompt( <w>, <flag> ) . . . . . . . . set drop gap prompt flag1177*/1178void GTDropGapPrompt ( Widget w, Boolean flag )1179{1180GapTextWidget gap = (GapTextWidget) w;11811182gap->gap.drop_gap_prompt = flag;1183}118411851186/****************************************************************************1187**11881189*E gaptext.c . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here1190*/119111921193