hoenig@informatik.uni-kl.de (Helmut Hoenig) (03/23/90)
Submitted-by: Helmut Hoenig <hoenig@informatik.uni-kl.de> Posting-number: Volume 6, Issue 48 Archive-name: xcol/part02 Please excuse me for typing in the wrong number of parts in the Subject-entry of the first part of the posting. I recognized it just when it was gone. This time it is correct. This is the second and last part. Helmut Hoenig hoenig@informatik.uni-kl.de ---------------------------------------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: xcol.part2 xcol.man README # Wrapped by hoenig@popper on Wed Mar 21 16:47:56 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f xcol.part2 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xcol.part2\" else echo shar: Extracting \"xcol.part2\" \(36359 characters\) sed "s/^X//" >xcol.part2 <<'END_OF_xcol.part2' X/******************************************************************************** X * Textwindow-Functions * X ********************************************************************************/ X X Xvoid draw_message( num ) X int num; X/* draws upper (0) or lower (1) message-entry */ X{ Xint y; X X y = (num)?(tw_lines+1)*char_height:0; X X XClearArea( display, tw, 0, y, twidth, char_height, False ); X XSetForeground( display, gc, white ); X if (tw_message[num]) X { XSetFont( display, gc, tinfo->fid ); X XDrawString( display, tw, gc, X 0, y+tinfo->ascent, X tw_message[num], strlen( tw_message[num] ) ); X } X if (num) XDrawLine( display, tw, gc, 0, y, twidth, y ); X else XDrawLine( display, tw, gc, 0, char_height-1, twidth, char_height-1 ); X} X Xvoid set_message( msg, num ) X char *msg; X int num; X/* sets upper or lower message entry */ X{ X if (tw_message[num]) free(tw_message[num]); X if (msg) X { tw_message[num] = (char *)malloc((unsigned) strlen(msg)+1 ); X strcpy( tw_message[num], msg ); X } X else tw_message[num]=NULL; X X draw_message( num ); X} X Xvoid reset_messages() X{ Xchar mess[20]; X X if (act_offset) X { sprintf( mess, "*** UP (%d) ***", act_offset); X set_message( mess, 0 ); X } X else set_message( " click right button here to write file.", 0 ); X X if (act_offset+tw_lines<color_lines) X { sprintf( mess, "*** DOWN (%d) ***", color_lines-act_offset-tw_lines); X set_message( mess, 1 ); X } X else set_message( (char *)NULL, 1 ); X} X Xvoid draw_string( i ) X int i; X/* draws a color-line */ X{ Xint j; Xint y; Xint p1,p2; Xunsigned long fg_pixel, bg_pixel, help; X X j=i-act_offset; X if ((tw==(Window)0)||(j<0)||(j>=tw_lines)) return; X X y=(j+1)*char_height; X X fg_pixel = line[i].color->pixel; X if (fg_pixel==NotAllocated) X { fprintf(stderr, "fg_pixel of %s not allocated.\n", line[i].line->contents); X } X bg_pixel = line[i].help->pixel; X if (bg_pixel==NotAllocated) X { fprintf(stderr, "bg_pixel of %s not allocated.\n", line[i].line->contents); X } X X if (line[i].reverse) X { help = fg_pixel; X fg_pixel = bg_pixel; X bg_pixel = help; X } X X/* clearing the background */ X XSetForeground(display, gc, bg_pixel); X XFillRectangle( display, tw, gc, 0, y, twidth, char_height); X X XSetFont( display, gc, tinfo->fid ); X XSetForeground( display, gc, fg_pixel ); X X p1 = line[i].pos_in_line; X p2 = p1 + strlen( line[i].color->name ); X p1 = XTextWidth( tinfo, line[i].line->contents, p1 )+2*char_width; X p2 = XTextWidth( tinfo, line[i].line->contents, p2 )+2*char_width; X X XDrawString( display, tw, gc, X 2*char_width, y+tinfo->ascent, X line[i].line->contents, strlen(line[i].line->contents)-1 ); X X XSetForeground( display, gc, fg_pixel ); X XDrawLine( display, tw, gc, p1, y+char_height-2, p2, y+char_height-2 ); X X/* draws the pixmap (at least some planes of it) */ X XSetState( display, gc, (unsigned long)AllPlanes, (unsigned long)0, X GXxor, fg_pixel^bg_pixel ); X XCopyArea( display, grey_pixmap, tw, gc, 0, 0, char_width, char_height, twidth-3*char_width, y ); X XSetState( display, gc, fg_pixel, bg_pixel, X GXcopy, (unsigned long)AllPlanes ); X X if (i==act_line) X { XDrawRectangle( display, tw, gc, 0, y, twidth-1, char_height-1); X XFillRectangle( display, tw, gc, 0, y, 2*char_width, char_height); X XFillRectangle( display, tw, gc, twidth-2*char_width, y, 2*char_width, char_height); X XSetForeground( display, gc, bg_pixel ); X } X else XSetForeground( display, gc, fg_pixel ); X X/* drawing indicator 'bg', 'fg', or 'R' */ X if (line[i].reverse) X { if (line[i].assoc>=0) X { XDrawString( display, tw, gc, 0, y+tinfo->ascent, "bg", 2 ); X } X else X { XSetForeground( display, gc, black ); X XSetBackground( display, gc, white ); X XDrawImageString( display, tw, gc, 0, y+tinfo->ascent, "R", 1 ); X } X } X else X { if (line[i].assoc>=0) X XDrawString( display, tw, gc, 0, y+tinfo->ascent, "fg", 2 ); X } X} X Xvoid change_color( act_line, new_color ) X int act_line; X ColorDef *new_color; X/* complete change of the color in the given line */ X{ X if (act_line<0) return; X X/* change the string */ X string_exchange( &line[act_line], new_color ); X X/* allocate the color */ X exchange( &line[act_line].color, new_color ); X X/* update the window (exchange corresponding color too) */ X draw_string(act_line); X if (line[act_line].assoc>=0) X { exchange( &line[line[act_line].assoc].help, new_color ); X draw_string(line[act_line].assoc); X } X} X Xint redraw_tw( l1, l2 ) X int l1, l2; X/* redraws parts of the text-window */ X{ Xint i; X X if (l1==0) X { draw_message( 0 ); X l1++; X } X if (l2>tw_lines) X { draw_message( 1 ); X l2=tw_lines; X } X for (i=l1;i<=l2;i++) draw_string( act_offset+i-1 ); X} X X/*----------------------------------------------------------------------------*/ X Xvoid show_string( row, text ) X int row; X TextLine *text; X{ X if (text) X { XSetForeground( display, gc, white ); X XFillRectangle( display, tw, gc, 0, row*char_height, twidth, char_height ); X XSetForeground( display, gc, black ); X XDrawString( display, tw, gc, X 2*char_width, row*char_height+tinfo->ascent, X text->contents, strlen(text->contents) ); X } X else X { XSetForeground( display, gc, black ); X XFillRectangle( display, tw, gc, 0, row*char_height, twidth, char_height ); X } X} X Xvoid show_text( i ) X int i; X/* shows the part of the text, where line i occurred. The old contents of the X * text-window is stored in a pixmap if possible. X */ X{ XTextLine *upper,*lower; Xint upper_i,lower_i; XXEvent event; XPixmap back; X X back = XCreatePixmap( display, tw, twidth, (tw_lines+2)*char_height, DefaultDepthOfScreen(screen) ); X if (back) X { XCopyArea( display, tw, back, gc, X 0, 0, twidth, (tw_lines+2)*char_height, X 0, 0 ); X } X X XGrabPointer(display, tw, False, X ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, X tw, text_cursor, CurrentTime ); X XSetFont( display, gc, tinfo->fid ); X X upper = line[i].line; X upper_i = i-act_offset+1; X XSetForeground( display, gc, grey ); X XFillRectangle( display, tw, gc, 0, upper_i*char_height, twidth, char_height ); X XSetForeground( display, gc, black ); X XDrawString( display, tw, gc, X 2*char_width, upper_i*char_height+tinfo->ascent, X upper->contents, strlen(upper->contents) ); X X lower = upper; X upper = upper; X lower_i = upper_i + 1; X upper_i--; X X while( ( upper_i>=0 )||(lower_i<=tw_lines+1) ) X { if ( upper_i>=0 ) X { if (upper) upper=upper->previous; X show_string( upper_i--, upper ); X } X if (lower_i<=tw_lines+1) X { if (lower) lower=lower->next; X show_string( lower_i++, lower ); X } X } X X XWindowEvent( display, tw, ButtonPressMask|ButtonReleaseMask, &event ); X X XUngrabPointer( display, CurrentTime ); X if (back) X { XCopyArea( display, back, tw, gc, X 0, 0, twidth, (tw_lines+2)*char_height, X 0, 0 ); X XFreePixmap( display, back ); X } X else redraw_tw( 0, tw_lines+1 ); X} X X/*----------------------------------------------------------------------------*/ X Xvoid write_quest( num ) X int num; X/* waits for a confirmation before the file is written with backup. */ X{ XXEvent event; X X set_message( " confirm writing with right button !", num ); X XBell( display, 10 ); X X XGrabPointer(display, tw, False, X ButtonPressMask|LeaveWindowMask, GrabModeAsync, GrabModeAsync, None, quest_cursor, CurrentTime ); X XWindowEvent( display, tw, ButtonPressMask|LeaveWindowMask, &event ); X X if ((event.xany.type==ButtonPress)&&(event.xbutton.button==Button3)) X { char back_name[MAXPATHLEN]; X X strcpy( back_name, file_name ); X strcat( back_name, "~" ); X X if (rename( file_name, back_name )) X { set_message(" can't create backup. writing aborted.", num); X } X else X { if (write_file( file_name )) X set_message(" writing failed.", num); X else set_message(" file written with backup.", num); X } X } X else set_message(" writing aborted.", num); X X XUngrabPointer( display, CurrentTime ); X} X X/*----------------------------------------------------------------------------*/ X Xvoid new_assoc( act ) X int act; X/* the function waits, until the button is released or the mouse is moved X * into an associated line. If both lines were already connected, they get X * disconnected. If no line was connected, the first line will get the X * foreground and the second line the background of the association. X */ X{ XXEvent event; Xint new; X X if (line[act].assoc>=0) X { set_message( " move to associated line to disconnect.", 0 ); X } X else set_message( " move to background to connect.", 0 ); X X XGrabPointer(display, tw, False, X ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, tw, updown_cursor, CurrentTime ); X X new = act; X do X { XWindowEvent( display, tw, ButtonReleaseMask|PointerMotionMask, &event ); X if (event.xany.type==MotionNotify) X { new = (event.xmotion.y/char_height)+act_offset-1; X if (new!=act) break; X } X } X while( event.xany.type!=ButtonRelease ); X X if (new==act) X { if (line[act].assoc<0) X { line[act].reverse^=1; X } X else X { ColorDef *help; X X help = line[act].color; X change_color( act, line[line[act].assoc].color ); X change_color( line[act].assoc, help ); X } X reset_messages(); X } X else X { if (line[act].assoc<0) X { if (line[new].assoc<0) X { set_message( " new association set.", 0 ); X XBell( display, 5 ); X X line[act].assoc = new; X exchange( &line[act].help, line[new].color ); X line[act].reverse = 0; X X line[new].assoc = act; X exchange( &line[new].help, line[act].color ); X line[new].reverse = 1; X X draw_string( new ); X draw_string( act ); X } X else X { set_message( " line already connected.", 0 ); X XBell( display, 10 ); X } X } X else X { if (line[act].assoc==new) X { set_message( " disconnected.", 0 ); X XBell( display, 5 ); X line[act].assoc = -1; X line[new].assoc = -1; X draw_string( new ); X draw_string( act ); X } X else X { set_message( " lines not associated.", 0 ); X XBell( display, 10 ); X } X } X } X X while (event.xany.type!=ButtonRelease) X { XWindowEvent( display, tw, ButtonReleaseMask, &event ); X } X XUngrabPointer( display, CurrentTime ); X} X X/*----------------------------------------------------------------------------*/ X Xvoid tw_event( event ) X XEvent *event; X/* event-execution for the text-window */ X{ X switch( event->xany.type ) X { X case ConfigureNotify: X { XEvent help; X int tw_new; X X tw_new = (event->xconfigure.height/char_height)-2; X if ((twidth==event->xconfigure.width)&&(tw_lines==tw_new)) break; X X twidth = event->xconfigure.width; X tw_lines = tw_new; X X if (tw_lines>color_lines) tw_lines=color_lines; X if (act_offset+tw_lines>color_lines) X act_offset = color_lines-tw_lines; X X redraw_tw( 0, tw_lines+1 ); X XSync(display, 0); X while( XCheckWindowEvent( display, tw, ExposureMask, &help ) ); X X break; X } X X case KeyPress: X { char sign; X KeySym keysym; X X XLookupString(event, &sign, 1, &keysym, NULL); X if (sign=='q') exit(0); X break; X } X X case Expose: X { XEvent help; X int first, first2; X int last, last2; X X first = event->xexpose.y/char_height; X last = (event->xexpose.y + event->xexpose.height)/char_height+1; X X while( XCheckWindowEvent( display, tw, ExposureMask, &help ) ) X { first2 = help.xexpose.y/char_height; X last2 = (help.xexpose.y + help.xexpose.height)/char_height+1; X X if (first2 < first) first = first2; X if (last2 > last) last = last2; X } X redraw_tw( first, last ); X break; X } X X case ButtonPress: X { int i; X int old_act; X int offset_delta; X X i= (event->xbutton.y / char_height)-1; X X /* has the header or footer of the textwindow been selected ? */ X if (i<0) X { if (event->xbutton.button==Button3) X { write_quest(0); X return; X } X else if (act_offset) X { offset_delta=(event->xbutton.button==Button1)?1:10; X if (act_offset-offset_delta<0) X offset_delta = act_offset; X act_offset -= offset_delta; X XCopyArea( display, tw, tw, gc, X 0, char_height, twidth, (tw_lines-offset_delta)*char_height, X 0, (offset_delta+1)*char_height ); X redraw_tw( 1, offset_delta+1 ); X } X else XBell(display, 10); X break; X } X if (i>=tw_lines) X { if (event->xbutton.button==Button3) X { write_quest(1); X return; X } X else if (act_offset+tw_lines<color_lines) X { offset_delta=(event->xbutton.button==Button1)?1:10; X if (act_offset+offset_delta>color_lines-tw_lines) X offset_delta = color_lines-act_offset-tw_lines; X act_offset += offset_delta; X XCopyArea( display, tw, tw, gc, X 0, (offset_delta+1)*char_height, X twidth, (tw_lines-offset_delta)*char_height, X 0, char_height ); X redraw_tw( tw_lines-offset_delta+1, tw_lines ); X } X else XBell(display, 10); X break; X } X i+=act_offset; X X /* action on a textline depending on the button */ X switch(event->xbutton.button) X { X case Button2: X old_act = act_line; X act_line = -1; X draw_string( old_act ); X new_assoc( i ); X act_line=i; X draw_string( act_line ); X return; X X case Button1: X old_act = act_line; X act_line = i; X draw_string( old_act ); X draw_string( act_line ); X break; X X case Button3: X old_act = act_line; X act_line = i; X draw_string( old_act ); X show_text( act_line ); X draw_string( act_line ); X break; X X break; X } X } /* end case ButtonPress */ X } /* end switch(type) */ X reset_messages(); X} X X/*----------------------------------------------------------------------------*/ X XWindow create_textwindow( fname ) X char *fname; X{ XWindow tw; XXSizeHints hints; XXWMHints normal_hints; XXClassHint class_hints; X Xstatic char *iname = "TextView"; Xchar wname[MAXPATHLEN+10]; Xchar *name_ptr; X X/* parsing the geometry */ X hints.flags = PSize | PMaxSize | PMinSize | PResizeInc; X X if (color_lines<4) hints.min_height = (color_lines+2) * (char_height); X else hints.min_height = 7 * (char_height); X hints.min_width = 20 * char_width; X X if (color_lines>50) tw_lines = 25; X else tw_lines = color_lines; X hints.width = longest_colored+ 6 * char_width; X hints.height= (tw_lines+2) * (char_height); X act_offset = 0; X X hints.max_height = (color_lines+2) * (char_height); X hints.max_width = 2*(longest_colored); X X hints.width_inc = char_width; X hints.height_inc = char_height; X X twidth = hints.width; X X/* names */ X name_ptr = rindex( fname, '/' ); X if (name_ptr) fname = name_ptr+1; X X sprintf( wname, "TextView '%s'", fname ); X name_ptr = wname; X X tw = XCreateSimpleWindow( display, RootWindowOfScreen(screen), X 0, 0, hints.width, hints.height, 3, grey, black ); X X/* class-hints */ X class_hints.res_name = "xcol"; X class_hints.res_class= "XCol"; X X/* normal-hint */ X normal_hints.flags = StateHint | WindowGroupHint; X X normal_hints.initial_state = NormalState; X normal_hints.window_group = mw; X X#ifdef XTextProperty X{ XXTextProperty window_name, icon_name; X X XStringListToTextProperty( &name_ptr, 1, &window_name ); X XStringListToTextProperty( &iname, 1, &icon_name ); X X XSetWMProperties( display, tw, &window_name, &icon_name, (char **)0, 0, X &hints, &normal_hints, &class_hints ); X X XFree( (char *)window_name.value ); X XFree( (char *)icon_name.value ); X} X#else X XSetStandardProperties( display, tw, name_ptr, iname, None, (char **)0, 0, &hints ); X XSetNormalHints( display, tw, &normal_hints ); X XSetClassHint( display, tw, &class_hints ); X#endif X X XSelectInput( display, tw, X ExposureMask | ButtonPressMask | StructureNotifyMask | X KeyPressMask | EnterWindowMask | LeaveWindowMask ); X XDefineCursor( display, tw, tw_cursor ); X XMapRaised( display, tw ); X return( tw ); X} X X X/******************************************************************************** X * Subwindow-Functions * X ********************************************************************************/ X X Xvoid destroy_subwindow( i ) X int i; X/* destroys the tiny subwindow and its associated colors */ X{ XColorDef *act; X X act = color[i]; X while( act->associated ) X { act = act->associated; X unload_color( act ); X } X XDestroyWindow( display, subw ); X} X Xvoid create_subwindow( i ) X int i; X/* creates, maps and draws a tiny information-window for the given color */ X{ XXSetWindowAttributes attrib; Xint x, y; Xint subs; Xint j; XColorDef *shades[MAX_COLS]; XColorDef *act; Xint bord=6; X X/* what associated color should be shown ? */ X act = color[i]; X subs = 0; X shades[subs++] = act; X while( act->associated ) X { act = act->associated; X shades[subs++]=act; X } X if (subs>gran+1) X { for (j=0;j<(gran);j++) X { shades[j+1]= shades[1+(j*(subs-2))/(gran-1)]; X } X subs=gran+1; X } X for (j=0;j<subs;j++) load_color( shades[j] ); X X/* compute size */ X sdx = XTextWidth( finfo, color[i]->name, strlen(color[i]->name) )+4; X sdy = finfo->ascent + finfo->descent+2; X if (subs>1) X { int palette_width=8; X X sdy += 14; X if (sdx<(subs*palette_width)) X { do X { sdx=subs*palette_width; X palette_width--; X } X while( (sdx+2*bord>dx)&&(palette_width>3) ); X } X subcols = subs; X } X else X { subcols = subs = 0; X } X X/* compute position */ X if (color[i]->x < dx/2) x = color[i]->x + BO; X else x = color[i]->x -BO -(2*bord) -sdx; X if (x+sdx+(2*bord)>dx) x = dx - sdx - (2*bord); X if (x<0) x=0; X X if (color[i]->y < dy/2) y = color[i]->y + BO; X else y = color[i]->y -BO -(2*bord) -sdy; X X/* create, map and draw */ X subw = XCreateSimpleWindow( display, mw, x, y, sdx, sdy, bord, color[i]->pixel, black ); X attrib.save_under = True; X XChangeWindowAttributes( display, subw, CWSaveUnder, &attrib ); X XMapRaised( display, subw ); X X XSetFont( display, gc, finfo->fid ); X XSetForeground( display, gc, white ); X XSetBackground( display, gc, black ); X XDrawImageString( display, subw, gc, X (sdx-XTextWidth( finfo, color[i]->name, strlen(color[i]->name)))>>1, X finfo->ascent, color[i]->name, strlen( color[i]->name ) ); X if (subs) X { for (j=0;j<subs;j++) X { X XSetForeground( display, gc, shades[j]->pixel ); X XFillRectangle( display, subw, gc, 2+j*(sdx-2)/subs, sdy-12, (j+1)*(sdx-2)/subs-(2+j*(sdx-2)/subs), 10); X } X } X} X X/*----------------------------------------------------------------------------*/ X X/* LittleBox draws 2 rectangles around a color-field of the subwindow */ X#define LittleBox(col) \ X XDrawRectangle( display, subw, gc, \ X 1+col*(sdx-2)/subcols, sdy-13, \ X (col+1)*(sdx-2)/subcols-(2+col*(sdx-2)/subcols)+1, 11); \ X XDrawRectangle( display, subw, gc, \ X 1+col*(sdx-2)/subcols-1, sdy-13-1, \ X (col+1)*(sdx-2)/subcols-(2+col*(sdx-2)/subcols)+1+2, 11+2) X X Xvoid sub_select( line_index, i, help_color ) X int line_index, i, help_color; X/* select a sub-color */ X{ XColorDef *shades[MAX_COLS]; XColorDef *act; Xint subs, j; XXEvent event; Xint col_index; /* current index to the shades-field */ Xint old_col_index; /* last index to the shades-field */ X X/* collect shades (shades[0] is used for the old value of the color) */ X if (help_color) shades[0] = line[line_index].help; X else shades[0] = line[line_index].color; X X act = color[i]; X subs = 1; X shades[subs++] = act; X while( act->associated ) X { act = act->associated; X shades[subs++]=act; X } X X if (subs>gran+1) X { for (j=0;j<(gran);j++) X { shades[j+2]= shades[2+(j*(subs-3))/(gran-1)]; X } X } X X/* first exchange of the color */ X col_index = 0; X if (help_color) X { exchange( &line[line_index].help, shades[col_index+1] ); X draw_string( line_index ); X } X else change_color( line_index, shades[col_index+1] ); X X/* if there are no associated colors, the selection is done */ X if (subs<=2) return; X X col_index=0; X old_col_index=0; X XSetForeground( display, gc, white ); X LittleBox( col_index ); X X/* warp the pointer to the main color of the subwindow */ X XWarpPointer( display, None, subw, 0, 0, 0, 0, ((sdx/subcols)>>1)+2, sdy-7 ); X XGrabPointer(display, subw, False, X ButtonPressMask | ButtonReleaseMask | PointerMotionMask, X GrabModeAsync, GrabModeAsync, X subw, subsel_cursor, CurrentTime ); X X do X { XWindowEvent( display, subw, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &event ); X if (event.xany.type!=ButtonRelease) X { X if (event.xany.type==MotionNotify) X { while(XCheckMaskEvent(display, PointerMotionMask, &event)); X X col_index = (event.xmotion.x-1)*subcols/(sdx-2); X if (col_index<0) col_index=0; X if (col_index>=subcols) col_index=subcols-1; X X if ((event.xmotion.y<sdy-13)||(event.xmotion.y>sdy-2)) X { col_index = -1; X } X } X else col_index = -1; /* another ButtonPress == abort */ X X if (old_col_index!=col_index) X { if (old_col_index>=0) X { XSetForeground( display, gc, black ); X LittleBox( old_col_index ); X } X if (col_index>=0) X { XSetForeground( display, gc, white ); X LittleBox( col_index ); X } X old_col_index = col_index; X if (help_color) X { exchange( &line[line_index].help, shades[col_index+1] ); X draw_string( line_index ); X } X else change_color( line_index, shades[col_index+1] ); X } X } X } X while( event.xany.type==MotionNotify ); X X XUngrabPointer(display, CurrentTime); X XSetForeground( display, gc, black ); X LittleBox( old_col_index ); X/* warp pointer back to its former position */ X XWarpPointer( display, None, mw, 0, 0, 0, 0, shades[1]->x, shades[1]->y ); X/* XSync(display, 1); */ X} X X X/******************************************************************************** X * main-window-functions * X ********************************************************************************/ X X Xint act_color( x, y ) X int x, y; X/* queries the next color in range of the mouse-pointer */ X{ Xint i; Xint min_dist; Xint min_i; Xint dx1, dy1; X X min_dist = dy*dy+dx*dx; X X for (i=0;i<color_number;i++) X { dx1 = abs(color[i]->x-x); X dy1 = abs(color[i]->y-y); X X if (dx1*dx1+dy1*dy1<min_dist) X { min_dist = dx1*dx1+dy1*dy1; X min_i = i; X } X } X if (min_dist<(BO)*(BO)) X return(min_i); X else X return(-1); X} X X/*----------------------------------------------------------------------------*/ X X#define XPos(r, g, b) ( (BO>>1)+2+ \ X ( (reverse) ? (127+(255-r)-((255-b)>>1)) \ X : (127+r-((b)>>1)) \ X ) * (dx-BO-4)/384 \ X ) X#define YPos(r, g, b) ( (BO>>1)+2+ \ X ( (reverse) ? (g+((255-b)>>1)) \ X : ((255-g)+(b>>1)) \ X ) * (dy-BO-4)/384 \ X ) X Xvoid redraw_window() X/* redraws the cube and the color-boxes in the main window */ X{ Xint i, j, op; Xint ex[8], ey[8]; Xint dummy; XWindow root; X X XGetGeometry( display, mw, &root, &dummy, &dummy, &dx, &dy, &dummy, &dummy ); X if (BO_def) X BO = BO_def; X else X { BO = (dx/50); X if ((dy/50)>BO) BO=(dy/50); X } X XClearWindow( display, mw ); X X/* draw the cube */ X XSetForeground( display, gc, white ); X for (i=0;i<8;i++) X { ex[i] = XPos( ((i&1)?255:0), ((i&2)?255:0), ((i&4)?255:0) ); X ey[i] = YPos( ((i&1)?255:0), ((i&2)?255:0), ((i&4)?255:0) ); X } X for (i=0;i<8;i++) X { for (j=0;j<3;j++) X { op = i^(1<<j); X if (op<i); X XDrawLine(display, mw, gc, ex[i], ey[i], ex[op], ey[op]); X } X } X X/* draw the boxes */ X for (i=0;i<color_number;i++) X { X color[i]->x = XPos(color[i]->r, color[i]->g, color[i]->b); X color[i]->y = YPos(color[i]->r, color[i]->g, color[i]->b); X X XSetForeground( display, gc, color[i]->pixel ); X XFillRectangle( display, mw, gc, X color[i]->x-(BO>>1), color[i]->y-(BO>>1), BO, BO); X } X XFlush(display); X} X X/*----------------------------------------------------------------------------*/ X Xmw_event( event ) X XEvent *event; X{ Xstatic int new_i; Xstatic int old_i= -1; X X switch( event->xany.type ) X { X case Expose: X while(XCheckWindowEvent( display, mw, ExposureMask, event )); X X if (event->xexpose.count==0) redraw_window(); X break; X X case MotionNotify: X while( XCheckWindowEvent( display, mw, PointerMotionMask, event ) ); X new_i = act_color( event->xmotion.x, event->xmotion.y ); X if ((old_i!=new_i)&&(old_i>=0)) X { destroy_subwindow(old_i); X old_i = -1; X } X if (old_i!=new_i) X { create_subwindow(new_i); X old_i = new_i; X } X break; X X case EnterNotify: X update_map(); X break; X X case LeaveNotify: X if (old_i>=0) X { destroy_subwindow(old_i); X old_i = -1; X } X break; X X case ButtonPress: X switch (event->xbutton.button) X { X case Button1: X { if ((tw)&&(old_i>=0)) X { sub_select( act_line, old_i, 0 ); X } X else X { if (old_i>=0) X { sub_select( 0, old_i, 0 ); X XStoreBytes( display, line[0].color->name, strlen(line[0].color->name) ); X XBell(display, 10); X } X } X break; /* end switch(button) */ X } X X case Button2: X { if ((tw)&&(act_line>=0)&&(old_i>=0)) X { if (line[act_line].assoc<0) X sub_select( act_line, old_i, 1 ); X else sub_select( line[act_line].assoc, old_i, 0 ); X } X break; /* end switch(button) */ X } X X case Button3: X { ColorDef *act; X char *short_name; X char *name; X char name_copy[30]; X int name_length; X X name = short_name = NULL; X X if ((tw)&&(act_line>=0)) X { short_name = cut_digits( line[act_line].color->name ); X } X else X { if (tw==(Window)0) X { name = XFetchBytes( display, &name_length ); X if (name_length<28) X { strncpy( name_copy, name, name_length ); X name_copy[ name_length ] = '\0'; X short_name = cut_digits( name ); X } X XFree( name ); X } X } X if (short_name) X { act = find_color( short_name ); X if (act) X XWarpPointer( display, None, mw, 0, 0, 0, 0, X XPos( act->r, act->g, act->b ), YPos( act->r, act->g, act->b ) ); X } X if (name) XFree(name); X X break; /* end switch(button) */ X } X break; /* end switch(type) */ X } X X case KeyPress: X { char sign; X KeySym keysym; X X XLookupString(event, &sign, 1, &keysym, NULL); X if (sign=='q') exit(0); X break; X } X } X} X X/*----------------------------------------------------------------------------*/ X Xvoid create_mainwindow( argc, argv, geometry ) X int argc; X char **argv; X char *geometry; X{ Xint x, y; Xint result; XXSizeHints hints; XXWMHints normal_hints; XXClassHint class_hints; Xstatic char *window_string = "ColorView"; Xstatic char *icon_string = "ColorView"; X X/* parsing the geometry */ X if (geometry) X result = XParseGeometry( geometry, &x, &y, &dx, &dy ); X else result = 0; X X hints.flags = PAspect | PMinSize | PMaxSize; X hints.min_width = hints.min_height = 100; X hints.max_width = hints.max_height = HeightOfScreen(screen); X X hints.min_aspect.x = 1; hints.min_aspect.y = 1; X hints.max_aspect.x = 1; hints.max_aspect.y = 1; X X if ((result&XValue)&&(result&YValue)) X { hints.x = x; X hints.y = y; X hints.flags |= USPosition; X } X else X { x=0; X y=0; X } X if ((result&WidthValue)&&(result&HeightValue)) X { hints.width = dx; X hints.height = dy; X hints.flags |= USSize; X } X else X { hints.width = dx = HeightOfScreen(screen)/3; X hints.height = dy = HeightOfScreen(screen)/3; X hints.flags |= PSize; X } X X mw = XCreateSimpleWindow( display, RootWindowOfScreen(screen), X x, y, dx, dy, 3, WhitePixelOfScreen(screen), BlackPixelOfScreen(screen) ); X X/* class-hints */ X class_hints.res_name = "xcol"; X class_hints.res_class= "XCol"; X X/* normal-hint */ X normal_hints.flags = StateHint | WindowGroupHint; X normal_hints.initial_state = NormalState; X normal_hints.window_group = mw; X X#ifdef XTextProperty X{ XXTextProperty window_name, icon_name; X X XStringListToTextProperty( &window_string, 1, &window_name ); X XStringListToTextProperty( &icon_string, 1, &icon_name ); X X XSetWMProperties( display, mw, &window_name, &icon_name, argv, argc, X &hints, &normal_hints, &class_hints ); X X XFree( (char *)window_name.value ); X XFree( (char *)icon_name.value ); X} X#else X XSetStandardProperties( display, mw, window_string, icon_string, None, argv, argc, &hints ); X XSetNormalHints( display, mw, &normal_hints ); X XSetClassHint( display, mw, &class_hints ); X#endif X} X X X/******************************************************************************** X * initialization and helps * X ********************************************************************************/ X X Xvoid help() X{ Xprintf("ColorView:\n"); Xprintf("\tThe colors of the rgb.txt-file of the server can be selected\n"); Xprintf("\tin this window. The Colors are sorted by their RGB-values. Colors\n"); Xprintf("\twith different intensity, but equal names, are grouped together.\n"); Xprintf("\n"); Xprintf("\t\tButton1:\tselect color for active line.\n"); Xprintf("\t\tButton2:\tselect help-color for active line.\n"); Xprintf("\t\tButton3:\twarp to color of active line.\n"); Xprintf("\t\t'q':\t\tquit the program.\n"); Xprintf("\n"); Xprintf("TextView:\n"); Xprintf("\tAll appearances of color-names in a textfile are collected and\n"); Xprintf("\tdisplayed in this window. For each line, the color and an additional\n"); Xprintf("\thelp-color can be set.\n"); Xprintf("\n"); Xprintf("in textline:\tButton1:\tselect line as active line.\n"); Xprintf("\t\tButton2:\ttoggle reverse-mode / make association\n"); Xprintf("\t\tButton3:\tshow line in textfile.\n"); Xprintf("\n"); Xprintf("in header or footer:\n"); Xprintf("\t\tButton1 (Button2):\tscroll by 1 (10), if possible.\n"); Xprintf("\t\tButton3:\twrite file with backup (after confirmation).\n"); X} X Xvoid usage() X{ X printf("usage:\txcol [options]\n\n"); X printf("options:\n"); X printf("\t<name>\t\tname of the textfile to be edited.\n"); X printf("\t-rv\t\tcolor-positions are reversed in the cube.\n"); X printf("\t-b<n>\t\tsize of color blocks is set to constant <n>.\n"); X printf("\t-gran<n>\tsets maximum number of associated colors to <n>.\n"); X printf("\t-dark<n>\tsets the percentage of the intensity of other colors.\n"); X X printf("\t-strings\tnames of colors in the file are only recognized\n"); X printf("\t\t\twhen used in a string (useful for C-Sources).\n"); X X printf("\t+<char_list>\tadd characters to list of 'space'-letters.\n" ); X X printf("\t-case\t\tconvert color-strings to correct case.\n"); X printf("\t-help\t\tprint some instructions (usage of buttons).\n"); X printf("\t-file <name>\tname of a different 'rgb.txt'-file.\n"); X X printf("\n"); X printf("\t-display <display_name>\n"); X printf("\t-geometry <geometry>\n"); X exit(0); X} X X/*----------------------------------------------------------------------------*/ X Xmain( argc, argv ) X int argc; X char **argv; X{ Xint disparg=0; Xchar *geometry=NULL; Xchar linebuffer[80]; /* buffer for lines of the color-file */ X Xchar *name; XColorDef act; X XFILE *fp; Xchar *rgb_file; Xint i, l; XXEvent event; X Xint last; X X file_name = NULL; X rgb_file = NULL; X X set_default_spaces(); X X/* parse some parameters */ X for (i=1;i<argc;i++) X { if (strcmp(argv[i], "-display")==0) disparg = ++i; X else if (strcmp(argv[i], "-geometry")==0) geometry= argv[++i]; X else if (strcmp(argv[i], "-file")==0) rgb_file = argv[++i]; X else if (strcmp(argv[i], "-rv")==0) reverse = 1; X else if (strncmp(argv[i], "-b", 2)==0) BO_def = atoi(&argv[i][2]); X else if (argv[i][0]=='+') X { l = strlen(argv[i]); X while(l-->1) space_char[argv[i][l]]=1; X } X else if (strncmp(argv[i], "-gran", 5)==0) X { gran = atoi(&argv[i][5]); X if (gran==0) gran=11; X } X else if (strncmp(argv[i], "-dark", 5)==0) X { darkness = atoi(&argv[i][5]); X if (darkness>100) darkness=100; X } X else if (strcmp(argv[i], "-help")==0) help(); X else if (strcmp(argv[i], "-case")==0) original=1; X else if (strcmp(argv[i], "-strings")==0) X { memset( space_char, 0, sizeof(space_char) ); X space_char['"'] = 1; X } X else if (argv[i][0]=='-') usage(); X else file_name = argv[i]; X } X X if ((display = XOpenDisplay( (disparg>0)?argv[disparg]:NULL ))==NULL) X { fprintf(stderr, "*** can't open display. ***\n"); X exit(0); X } X screen = ScreenOfDisplay(display, DefaultScreen(display)); X cells = CellsOfScreen(screen); X X if (cells<256) X { fprintf(stderr, "You don't have enough color-cells to use this program.\n" ); X exit(0); X } X if (cells>MAX_CELLS) X { fprintf(stderr, "There are many color-cells on your screen.\n" ); X cells=MAX_CELLS; X } X X/* load textfonts */ X finfo = XLoadQueryFont(display, COLOR_FONT ); X tinfo = XLoadQueryFont(display, TEXT_FONT ); X char_height = tinfo->descent + tinfo->ascent; X char_width = tinfo->max_bounds.rbearing + tinfo->min_bounds.lbearing; X X/* load the file with colors */ X if (rgb_file) fp = fopen( rgb_file, "r" ); X else fp = fopen( RGB_FILE, "r" ); X X if (fp==NULL) X { fprintf( stderr, "unable to load the 'rgb.txt'-file.\n" ); X exit(0); X } X color_number=0; X load_standard( &std_black ); X load_standard( &std_white ); X load_standard( &std_grey ); X X while (fgets( linebuffer, sizeof linebuffer, fp )!=NULL) X { int n; X X linebuffer[strlen(linebuffer)-1]='\0'; X X n = sscanf(linebuffer, "%d %d %d", X &act.r, &act.g, &act.b); X X if (n==3) X { name = linebuffer; X while( !isalpha(*name) ) name++; X X act.name = (char *)malloc((unsigned)strlen(name)+1); X strcpy(act.name, name); X new_color( &act ); X } X } X fclose( fp ); X X/* sort the colors */ X if (reverse) X qsort( (char *)color, color_number, sizeof(ColorDef *), color_sort_r ); X else qsort( (char *)color, color_number, sizeof(ColorDef *), color_sort ); X X for (i=0;i<color_number;i++) X { ColorDef *act; X X brother_sort( &color[i] ); X act = color[i]; X while( act ) X { associated_sort( act ); X act = act->brother; X }; X } X X/* collect the color-names */ X color_names = 0; X for (i=0;i<color_number;i++) X { ColorDef *act, *assoc; X X act = color[i]; X if (act->pixel==Undefined) X { X /* if the unindexed name is not defined, the first associated X * entry of its list is copied onto it. X */ X assoc = act->associated; X memcpy( (char *)act, (char *)assoc, sizeof(ColorDef) ); X free( (char *)assoc ); X } X X do X { next_name( act ); X assoc = act->associated; X while( assoc ) X { next_name( assoc ); X assoc = assoc->associated; X } X act = act->brother; X } X while (act); X } X qsort( (char *)cname, color_names, sizeof(ColorString), color_name_sort ); X last = 0; X first[0] = &cname[0]; X for (i=0;i<color_names;i++) X { if (cname[i].name[0]!=last) X { do X { last++; X first[last] = &cname[i]; X } X while( cname[i].name[0]!=last ); X } X } X while( last<255 ) X { last++; X first[last] = &cname[i]; X } X X/* initializing XWindow stuff */ X grey_pixmap = XCreatePixmapFromBitmapData( display, RootWindowOfScreen(screen), X grey_bits, grey_width, grey_height, AllPlanes, 0, DefaultDepthOfScreen(screen) ); X gc = XCreateGC( display, RootWindowOfScreen(screen), (long)0, NULL); X XCopyGC(display, DefaultGCOfScreen(screen), (long)-1, gc); X XSetGraphicsExposures( display, gc, False ); X X create_mainwindow( argc, argv, geometry ); X create_new_map(); X XSetWindowColormap( display, mw, my_map ); X XSetWindowBackground( display, mw, black ); X XSetWindowBorder( display, mw, grey ); X X mw_cursor = XCreateFontCursor( display, XC_top_left_arrow ); X tw_cursor = mw_cursor; X subsel_cursor = mw_cursor; X text_cursor = XCreateFontCursor( display, XC_middlebutton ); X quest_cursor = mw_cursor; X updown_cursor = XCreateFontCursor( display, XC_sb_v_double_arrow ); X X#ifdef RECOLOR_CURSOR X/* the cursor have to get the pixel-values of my colormap X * not working the way i expected. i don't think it's my fault. X * only in the main-, not in the text-window, the colors are correct. X */ X { ColorDef *fg, *bg; /* Cursor Foreground/Background */ X XColor xfg, xbg; X X bg = find_color( "LightGoldenrod" ); X fg = find_color( "MidnightBlue" ); X load_color( bg ); X load_color( fg ); X xbg.pixel = bg->pixel; X xfg.pixel = fg->pixel; X XQueryColor( display, my_map, &xbg ); X XQueryColor( display, my_map, &xfg ); X X XRecolorCursor( display, mw_cursor, &xfg, &xbg ); X XRecolorCursor( display, text_cursor, &xfg, &xbg ); X XRecolorCursor( display, updown_cursor, &xfg, &xbg ); X } X#endif X X XDefineCursor( display, mw, mw_cursor ); X XSelectInput( display, mw, X ExposureMask | PointerMotionMask | X ButtonPressMask | LeaveWindowMask | EnterWindowMask | X KeyPressMask ); X X XMapRaised( display, mw ); X XSync( display, 0 ); X redraw_window(); X X/* loading the file */ X back_def = find_color( GREY_STRING ); X X if (file_name) X { X if (load_file( file_name )) X { if (color_lines>0) X { find_assocs(); X tw = create_textwindow( file_name ); X load_text_colors(); X if (only_mine) X { XSetWindowColormap( display, tw, my_map ); X } X } X else X printf("no colors found in your file.\n"); X }; X } X else X { loaded_text = (TextLine *)malloc( (unsigned)sizeof(TextLine) ); X loaded_text->next = loaded_text->previous = NULL; X loaded_text->contents = (char *)malloc( 6 ); X strcpy( loaded_text->contents, "white" ); X X line[0].line = loaded_text; X line[0].color = find_color( WHITE_STRING ); X line[0].help = find_color( BLACK_STRING ); X line[0].reverse = 0; X line[0].pos_in_line = 0; X line[0].assoc = -1; X X color_lines = 1; X } X X do X { XNextEvent( display, &event ); X if (event.xany.window==mw) X { mw_event( &event ); X } X else X { tw_event( &event ); X } X } X while(1); X} X X END_OF_xcol.part2 if test 36359 -ne `wc -c <xcol.part2`; then echo shar: \"xcol.part2\" unpacked with wrong size! fi # end of overwriting check fi if test -f xcol.man -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xcol.man\" else echo shar: Extracting \"xcol.man\" \(3400 characters\) sed "s/^X//" >xcol.man <<'END_OF_xcol.man' X.TH xcol 1 "5 March 1990" "X Version 11" X.SH NAME Xxcol \- change color-entries in textfiles X.SH SYNOPSIS X.B xcol X[-options ...] X[\fIfilename\fP] X.SH DESCRIPTION X.I XCol Xdisplays the colors defined in the \fIrgb.txt\fP-file of the XServer. XThe colors are sorted by their names and their RGB-values and shown Xin a cube in the \fIColorView\fP-Window (The positions represent the RGB-values). XSince there usually are Xmore colors defined in the file than cells in the colormap, entries with Xthe same name but different RGB-values for different intensities, are Xgrouped together. X.PP XIf a filename is given as a parameter, all occurrences of color-names in that Xfile are shown in an additional \fITextView\fP-Window. To change the colors, Xa text-line has to be made active. Afterwards a new color Xcan be selected in the ColorView-Window. To get a better Ximpression of the color, a help-color (background) can be selected for each Xtext-line. If 2 lines define a foreground and a background color, an Xassociation can be made and the colors of both lines can be selected together. X.SH "BUTTONS" Xin \fIColorView\fP-Window X.RS X.TP 8 X.B left: Xselect color for the active line. X.PD 0 X.IP middle: Xselect help-color for the active line. X.IP right: Xwarp pointer to color of active line. X.PD 1 X.RE X.PP Xin \fITextView\fP-Window X.RS X.TP 8 X.B left: Xselect line as active line. X.PD 0 X.IP middle: Xtoggle reverse-mode or X.IP Xconnect/disconnect 2 lines. X.IP right: Xshow line in the textfile. X.PD 1 X.RE X.SH OPTIONS X.TP 8 X.B -rv XColor-positions are reversed in the cube. Some new colors can become visible Xin the area of the very bright colors. X.TP X.B -b<n> XThe size of color blocks is set to the constant <n>. By default, it Xdepends on the size of the ColorView-Window. X.TP X.B -gran<n> XThe maximum number of associated colors is set to <n>. By default, this value Xis 11. (You can see the effect when reaching the grey-field, where X101 associated entries are possibly available.) X.TP X.B -dark<n> XThe percentage of the intensity of other colors can be set (default: 50). It Xis easier to select a color, if the screen is darkened a little bit. X.TP X.B +<char_list> Xadd characters to list of 'space'-chars. The color-string in the textfile Xhas to occur between 2 'space'-chars to be recognized. By default, these Xletters are ' ', '\\t', '\\n', ':', '"'. X.TP X.B -strings XNames of colors in the file are only recognized when used in a string X(useful for C-Sources). This means that the list of 'space'-chars is Xset to '"' only. X.TP X.B -case XAll occurrences of color-names in wrong case are replaced by the color-name Xof the 'rgb.txt'-file. X.TP X.B -help Xprint some instructions (usage of buttons). X.TP X.B -file <name> Xname of a different 'rgb.txt'-file. X.SH FILES X/usr/lib/X11/rgb.txt X.SH "SEE ALSO" XX(1) X.SH BUGS XActually I wanted the program to work with the selection Xmechanism used in xterm (when no textfile is given), but it seems to be Xtoo complicated to use it here. XSo, the current version always stores the string of the color in CUT_BUFFER0. XIf anyone has an easy way to use the correct selection mechanism, please Xinform me. X.SH COPYRIGHT XCopyright 1990, University of Kaiserslautern. X.PP XAuthor: Helmut Hoenig (hoenig@informatik.uni-kl.de) X.PP XPermission to use, copy, modify, and distribute this Xsoftware for any purpose and without Xfee is hereby granted, provided that the above copyright Xnotice appear in all copies. END_OF_xcol.man if test 3400 -ne `wc -c <xcol.man`; then echo shar: \"xcol.man\" unpacked with wrong size! fi # end of overwriting check fi if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(646 characters\) sed "s/^X//" >README <<'END_OF_README' XXCol is a program to edit occurrences of color-names in text-files X(i.e. the '.twmrc'-file). It shows the available colors and you can Xchange the textfile by selecting new colors with the mouse. X XEven without editing a textfile, it gives you a good impression Xof the available colors (the colors defined in the 'rgb.txt'-file Xof the server). X XUse make to build the program. As there is only one XSource-Modul you can also use 'cc xcol.c -lX11 -o xcol'. X XThe program runs on X11R4. It should run on X11R3 too, but I Xalready had some small problems with the created colormap. XA manual page is included. X Xby Helmut Hoenig Xhoenig@informatik.uni-kl.de END_OF_README if test 646 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. # additional concatenation of splitted file if test -f xcol.part1 ; then echo ' concatenation of "xcol.part1" and "xcol.part2" to "xcol.c".' cat xcol.part1 xcol.part2 > xcol.c echo ' removing "xcol.part1" and "xcol.part2".' rm xcol.part1 xcol.part2 else echo ' unpack the first part now.' fi exit 0 dan ----------------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com 632 Petaluma Ave, Sebastopol, CA 95472 800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104 Opinions expressed reflect those of the author only.